Mermaid Subgraph Composition: Modular Complex Diagrams
As diagrams grow, they become harder to read. A flat flowchart with 40 nodes is incomprehensible; one organized into logical subgraphs is immediately clear. Mermaid's subgraph composition lets you nest workflows, group related steps, and build diagrams that scale from prototype to production architecture.
Why Subgraphs Matter
A subgraph is a visual and logical boundary—a container for related steps. Use them to:
- Organize by domain — authentication flows, payment processing, notification delivery as separate sections
- Hide complexity — show the big picture first, let readers drill into details
- Reuse patterns — common sub-workflows (retry loops, validation chains) become recognizable at a glance
- Reason about scope — each subgraph is a unit you can test, document, and own
flowchart TD
Start([User Action]) --> Auth{Authenticated?}
Auth -->|No| AuthFlow["🔐 Authentication"]
subgraph AuthFlow["Authentication Flow"]
A1[Request Credentials]
A2[Validate]
A3[Issue Token]
A1 --> A2 --> A3
end
Auth -->|Yes| BizFlow["💼 Business Logic"]
subgraph BizFlow["Process Request"]
B1[Fetch Data]
B2[Apply Rules]
B3[Transform]
B1 --> B2 --> B3
end
AuthFlow --> Response["✅ Success"]
BizFlow --> Response
Response --> End([Return])
Composition Patterns
Pattern 1: Top-Down Hierarchy
Organize by layers: entry → orchestration → specialized flows.
flowchart TD
Start([API Request]) --> Validate
subgraph HTTP["HTTP Layer"]
Validate["Validate Input"]
Rate["Rate Limit Check"]
Validate --> Rate
end
Rate --> Dispatch["Dispatch to Handler"]
subgraph Processing["Processing Layer"]
Enrich["Enrich Context"]
Transform["Transform Data"]
Persist["Persist State"]
Enrich --> Transform --> Persist
end
Dispatch --> Enrich
Persist --> Respond["Send Response"]
Respond --> End([Done])
Use this for: API handlers, middleware chains, multi-stage pipelines.
Pattern 2: Parallel Subgraphs
Multiple independent workflows that reconverge.
flowchart LR
Start([Publish Video]) --> Trigger
Trigger -->|Branch 1| Transcoding
Trigger -->|Branch 2| Thumbnail
Trigger -->|Branch 3| Metadata
subgraph Transcoding["🎬 Encoding"]
T1["Queue Job"]
T2["Transcode"]
T3["Upload"]
T1 --> T2 --> T3
end
subgraph Thumbnail["🖼️ Thumbnail"]
Th1["Extract Frame"]
Th2["Optimize"]
Th1 --> Th2
end
subgraph Metadata["📝 Metadata"]
M1["Detect Language"]
M2["Extract Captions"]
M1 --> M2
end
T3 --> Merge["Merge Results"]
Th2 --> Merge
M2 --> Merge
Merge --> Publish["Publish Asset"]
Use this for: concurrent tasks (encoding, indexing, notifications), deployment pipelines with parallel stages.
Pattern 3: Error Handling & Resilience
Subgraphs for retry logic, circuit breakers, and fallbacks.
flowchart TD
Req["Initiate Request"] --> Call{Call Remote API}
Call -->|Success| Parse["Parse Response"]
Call -->|Failure| Retry
subgraph Retry["Retry Logic"]
R1["Wait (exponential)"]
R2["Attempt"]
R3{Max Retries?}
R1 --> R2 --> R3
end
R3 -->|Retry| R1
R3 -->|Exhausted| Circuit
subgraph Circuit["Circuit Breaker"]
C1["Log Failure"]
C2["Mark Service Down"]
C3["Serve Stale Cache"]
C1 --> C2 --> C3
end
Parse --> Validate["Validate Shape"]
C3 --> Validate
Validate --> Success{Valid?}
Success -->|Yes| End([✅ Complete])
Success -->|No| Fallback["Use Default"]
Fallback --> End
Use this for: microservices, external API calls, fault tolerance flows.
Pattern 4: Nested Subgraphs (Multi-Level)
Subgraphs inside subgraphs for highly complex domains.
flowchart TD
Start([E-commerce Order]) --> CheckStock
subgraph Fulfillment["🛒 Fulfillment"]
CheckStock["Check Inventory"]
subgraph Inventory["Inventory System"]
I1["Query DB"]
I2["Lock Stock"]
I3["Confirm"]
I1 --> I2 --> I3
end
CheckStock --> I1
I3 --> Pick["Pick Items"]
subgraph Warehouse["Warehouse"]
W1["Locate Bins"]
W2["Pick & Scan"]
W3["QC Check"]
W1 --> W2 --> W3
end
Pick --> W1
W3 --> Pack["Pack Shipment"]
end
Pack --> Label["Generate Label"]
Label --> Ship["Hand to Carrier"]
Ship --> End([Shipped])
Use this for: complex business domains (fulfillment, underwriting, provisioning).
Styling & Clarity
Add emoji to subgraph titles for instant recognition—readers quickly scan for the section they need.
flowchart TD
User([User]) --> Auth
subgraph Auth["🔐 Auth & Identity"]
A1[Login]
A2[MFA]
A1 --> A2
end
Auth --> Payment
subgraph Payment["💳 Payment Processing"]
P1[Validate Card]
P2[Charge]
P3[Confirm]
P1 --> P2 --> P3
end
Payment --> Notify
subgraph Notify["📧 Notifications"]
N1[Send Email]
N2[SMS Alert]
N1 --> N2
end
Notify --> End([Success])
style Auth fill:#e1f5ff
style Payment fill:#fff3e0
style Notify fill:#f3e5f5
Anti-Patterns to Avoid
- Too Many Levels — Three subgraph nesting levels is a hard limit; beyond that, split into separate diagrams.
- Mixing Concerns — Don't group unrelated steps just to reduce visual clutter; each subgraph should have one clear purpose.
- Subgraph Naming — Use active, descriptive names (
"Authentication Flow"not"Auth"), especially for domain-heavy diagrams. - Overuse of Subgraph Styling — Stick to 2–3 distinct colors; too much variety is noise.
When to Reach for Separate Diagrams
If you need:
- Swimlanes for cross-functional roles (use
flowchartwith swimlane syntax, not subgraphs) - Multiple entry points (use separate diagrams linked in documentation)
- Recursive flows (each diagram level is a recursion; split into context → detail pairs)
Comparison: Subgraphs vs. Swimlanes
| Aspect | Subgraph | Swimlane |
|---|---|---|
| Nesting | Yes, multi-level | Limited (role-based rows) |
| Use case | Logical grouping, layers | Cross-functional workflows |
| Visual style | Container with border | Horizontal lane |
| Readability | Best for modules & scope | Best for actors & responsibility |
Subgraphs are for structure (what goes with what); swimlanes are for responsibility (who does what).
Rendering & Export
Build your subgraph-based diagrams in MermaidCreator's visual editor — drag nodes into subgraph groups, and the code generates automatically. Export as PNG or SVG to embed in docs, architecture decision records, or runbooks.
FAQ
Can I link between subgraphs? Yes. Arrows cross subgraph boundaries freely:
subgraph A["Step A"]
A1[Do Something]
end
subgraph B["Step B"]
B1[Do Another]
end
A1 --> B1
Should I use subgraph IDs or labels?
Always use labels (the second argument in subgraph ID ["Label"]). The label is what readers see; the ID is just internal.
How do I collapse or hide a subgraph in code? Mermaid doesn't natively support collapsing. Create a separate "summary" diagram that shows subgraph names as single nodes, and link to detail diagrams in your docs.
Start with flat flowcharts, then reach for subgraphs when complexity crosses the 15-node threshold. Your future readers will thank you.
Related posts
Mermaid Notes & Annotations: Document Diagram Intent & Context
Add clarity to diagrams with notes, comments, and annotations—best practices for labeling decisions, explaining asynchronous flows, and preventing ambiguity.
Mermaid reusable diagram components: snippets and templates
Build a diagram library. Share flowchart patterns, sequence templates, and system blocks across teams—DRY principle for technical drawings.