Mermaid Subgraphs: Group, Nest & Style Diagram Sections
Master Mermaid.js subgraphs to group related nodes, nest containers, set per-subgraph directions, and build cleaner architecture diagrams. Includes real-world examples.
What Are Subgraphs in Mermaid?
When a flowchart grows beyond a handful of nodes, it quickly becomes hard to read. Nodes scatter across the diagram with no sense of belonging. Subgraphs solve this by letting you group related nodes inside a labeled container — similar to how a bounding box or swim lane works in traditional diagramming tools.
Subgraphs are one of the most powerful features in Mermaid's flowchart syntax. They let you:
- Group nodes by service, team, or layer (frontend, backend, database)
- Nest containers for microservice architectures and cloud diagrams
- Set independent layout directions per section
- Connect entire groups to other nodes or groups
- Style containers with custom colors and borders
If you've been writing flat flowcharts and wondering why they look cluttered, subgraphs are the answer.
Basic Subgraph Syntax
A subgraph is declared with the subgraph keyword, followed by an optional ID and title, and closed with end:
flowchart TD
subgraph Frontend
A[React App] --> B[API Client]
end
subgraph Backend
C[Express Server] --> D[(PostgreSQL)]
end
B --> CTry in Editor →The key rules:
subgraph [id] ["title"]— Opens a subgraph. ID is used for linking; title is displayed.end— Closes the subgraph.- Nodes inside a subgraph are laid out within the container.
- You can still draw edges between nodes across different subgraphs.
ID vs Title
If you want a subgraph title with spaces, use quotes:
flowchart LR
subgraph fe["Frontend Layer"]
A[React]
end
subgraph be["Backend Layer"]
B[Node.js]
end
A --> BTry in Editor →Here fe and be are the IDs (used in edges), and "Frontend Layer" / "Backend Layer" are the displayed titles.
You can also omit the ID and just provide a title — Mermaid generates one internally:
flowchart TD
subgraph "API Services"
A[Auth] --> B[Users]
endTry in Editor →Connecting Subgraphs to Nodes and Other Subgraphs
You can draw edges from a node to a subgraph or from a subgraph to another subgraph. Mermaid treats the subgraph as a unit when used in an edge:
flowchart LR
Client([Browser]) --> fe
subgraph fe["Frontend"]
React[React App]
end
subgraph be["Backend"]
API[REST API] --> DB[(Database)]
end
fe --> beTry in Editor →Here, the edge fe --> be connects the two containers directly. Mermaid draws the arrow from the outer boundary of the first subgraph to the second.
Connecting Subgraph to Specific Nodes
You can also connect a subgraph to a specific node inside another subgraph:
flowchart TD
subgraph Client
Browser[Web Browser]
end
subgraph Server
Gateway[API Gateway] --> App[Application]
App --> DB[(PostgreSQL)]
end
Browser --> GatewayTry in Editor →Mixing subgraph-to-subgraph and node-to-node edges in the same diagram is perfectly valid.
Nested Subgraphs
Subgraphs can be nested inside other subgraphs to reflect hierarchical architectures:
flowchart TB
subgraph Cloud["AWS Cloud"]
subgraph VPC["VPC (172.16.0.0/16)"]
subgraph Public["Public Subnet"]
ALB[Load Balancer]
NAT[NAT Gateway]
end
subgraph Private["Private Subnet"]
ECS[ECS Service]
RDS[(RDS Database)]
Redis[(ElastiCache)]
end
end
S3[(S3 Bucket)]
CloudFront[CloudFront CDN]
end
Internet([Internet]) --> CloudFront
CloudFront --> ALB
ALB --> ECS
ECS --> RDS
ECS --> Redis
ECS --> S3
NAT --> InternetTry in Editor →Nesting depth is technically unlimited, but two to three levels is the practical maximum before diagrams become hard to read. Use nesting to show genuine hierarchy — cloud region → VPC → subnet → service — not just for visual grouping.
Per-Subgraph Direction
One of the most underused Mermaid features: each subgraph can have its own layout direction, independent of the root flowchart:
flowchart TB
subgraph RequestPath["Request Path (left-to-right)"]
direction LR
Client([Client]) --> LB[Load Balancer] --> API[API Server]
end
subgraph DataLayer["Data Layer (top-to-bottom)"]
direction TB
API2[API Server] --> Cache[(Redis)]
API2 --> DB[(PostgreSQL)]
end
API --> API2Try in Editor →This is powerful for diagrams where different sections have different natural flow directions. A request pipeline flows left-to-right, but a data hierarchy flows top-to-bottom. Combining both in one diagram — each section with its own direction — produces a far more readable result than forcing everything into a single direction.
Practical Example: Three-Tier Web Architecture
flowchart TB
subgraph "Presentation Tier"
Browser[Web Browser]
MobileApp[Mobile App]
end
subgraph "Application Tier"
direction LR
Gateway[API Gateway] --> Auth[Auth Service]
Gateway --> Users[User Service]
Gateway --> Orders[Order Service]
end
subgraph "Data Tier"
direction LR
UsersDB[(Users DB)]
OrdersDB[(Orders DB)]
Cache[(Redis Cache)]
Queue[Message Queue]
end
Browser --> Gateway
MobileApp --> Gateway
Auth --> UsersDB
Users --> UsersDB
Users --> Cache
Orders --> OrdersDB
Orders --> QueueTry in Editor →This is a clean, scannable architecture diagram. A developer joining the team instantly understands the three tiers and which services connect to which data stores.
Practical Example: Microservices System
flowchart LR
Client([External Client])
subgraph Edge["Edge Layer"]
direction TB
CDN[CDN] --> WAF[WAF]
WAF --> Gateway[API Gateway]
end
subgraph Services["Core Services"]
direction TB
AuthSvc[Auth Service]
UserSvc[User Service]
ProductSvc[Product Service]
OrderSvc[Order Service]
NotifSvc[Notification Service]
end
subgraph Infra["Infrastructure"]
direction TB
subgraph Databases["Databases"]
UserDB[(Users)]
ProductDB[(Products)]
OrderDB[(Orders)]
end
subgraph Messaging["Messaging"]
Kafka[Kafka]
end
subgraph Cache["Caching"]
Redis[(Redis)]
end
end
Client --> CDN
Gateway --> AuthSvc
Gateway --> UserSvc
Gateway --> ProductSvc
Gateway --> OrderSvc
UserSvc --> UserDB
UserSvc --> Redis
ProductSvc --> ProductDB
OrderSvc --> OrderDB
OrderSvc --> Kafka
Kafka --> NotifSvcTry in Editor →Styling Subgraphs
Using classDef
Apply classes to subgraph container backgrounds and borders:
flowchart TB
subgraph frontend["Frontend"]:::feStyle
A[React]
B[Next.js]
end
subgraph backend["Backend"]:::beStyle
C[Node.js]
D[(PostgreSQL)]
end
A --> C
B --> C
C --> D
classDef feStyle fill:#dbeafe,stroke:#3b82f6,stroke-width:2px,color:#1e3a8a
classDef beStyle fill:#dcfce7,stroke:#22c55e,stroke-width:2px,color:#14532dTry in Editor →The :::className syntax attaches a class to the subgraph container itself, letting you visually distinguish groups by color.
Styling Individual Nodes Inside Subgraphs
Nodes inside subgraphs are styled just like any other node:
flowchart TD
subgraph prod["Production"]
A[Web Server]:::critical
B[(Primary DB)]:::critical
end
subgraph standby["Standby"]
C[Replica Server]
D[(Replica DB)]
end
A -->|replicates| C
B -->|replicates| D
classDef critical fill:#fef2f2,stroke:#ef4444,stroke-width:2pxTry in Editor →Theme-Aware Subgraph Colors
If your diagrams are embedded on a site with light/dark mode, use Mermaid's theme variables instead of hard-coded colors so they adapt automatically:
%%{init: {'theme': 'base', 'themeVariables': {
'clusterBkg': '#f0f9ff',
'clusterBorder': '#0ea5e9',
'titleColor': '#0c4a6e'
}}}%%
flowchart TB
subgraph A["Service Group A"]
Node1[Service 1]
Node2[Service 2]
end
subgraph B["Service Group B"]
Node3[Service 3]
end
A --> BTry in Editor →The clusterBkg and clusterBorder variables control all subgraph containers globally.
Subgraph Gotchas and Common Mistakes
1. Missing `end` keyword
Every subgraph must have a matching end. Forgetting it causes a parse error:
%% WRONG — missing end
flowchart TD
subgraph A
Node1 --> Node2
subgraph B
Node3
endTry in Editor →%% CORRECT
flowchart TD
subgraph A
Node1 --> Node2
end
subgraph B
Node3
endTry in Editor →2. Node IDs Must Be Globally Unique
Even if two nodes are in different subgraphs, they share the same namespace. A inside "Frontend" and A inside "Backend" is the same node:
%% WRONG — both subgraphs share node "A"
flowchart TD
subgraph Frontend
A[React] --> B[Redux]
end
subgraph Backend
A[Express] --> C[(DB)]
endTry in Editor →%% CORRECT — unique IDs
flowchart TD
subgraph Frontend
feReact[React] --> feRedux[Redux]
end
subgraph Backend
beExpress[Express] --> beDB[(DB)]
endTry in Editor →3. Connecting to a Subgraph ID vs. a Node ID
flowchart LR
X[External] --> myGroup %% Edge to the subgraph container
X[External] --> A %% Edge to node A (which may be inside a subgraph)
subgraph myGroup
A[Node A] --> B[Node B]
endTry in Editor →Both are valid but produce different visual results. Arrow-to-container edges touch the container boundary; arrow-to-node edges touch the specific node.
4. Direction Inside Subgraphs Requires `flowchart`, Not `graph`
Per-subgraph direction only works with the flowchart keyword, not the older graph keyword:
%% WORKS
flowchart TB
subgraph A
direction LR
X --> Y
end
%% DOES NOT WORK (older syntax)
graph TB
subgraph A
direction LR
X --> Y
endTry in Editor →When to Use Subgraphs
Use subgraphs when:
- Your diagram has 6+ nodes and they form natural groups
- You're documenting a layered architecture (presentation / application / data)
- You need to show service ownership (team A owns these services, team B owns those)
- Your diagram represents a cloud architecture with regions, VPCs, and subnets
- You're showing phase groupings in a pipeline (build, test, deploy)
Don't use subgraphs when:
- Your diagram is simple enough to read without grouping
- You're adding subgraphs just for visual variety — they should reflect real structural relationships
- The nesting depth exceeds 3 levels — split the diagram instead
Subgraphs vs. Separate Diagrams
A common question: should you group with a subgraph, or create a separate diagram for each section?
Use subgraphs when: The groups need to show how they connect. A microservices diagram where you want to see frontend ↔ backend ↔ database relationships benefits from showing all three in one diagram with subgraph grouping.
Use separate diagrams when: Each section is complex enough to deserve its own diagram. A detailed database schema doesn't belong in the same diagram as a request flow. Link between them with text references or documentation navigation.
Complete Reference: Subgraph Syntax
flowchart [direction]
%% Basic subgraph
subgraph id["Title"]
nodes...
end
%% Subgraph with per-group direction
subgraph id2["Title 2"]
direction LR
nodes...
end
%% Nested subgraph
subgraph outer["Outer"]
subgraph inner["Inner"]
nodes...
end
end
%% Styled subgraph
subgraph styled["Styled Group"]:::myClass
nodes...
end
%% Edge to subgraph (touches container boundary)
externalNode --> id
%% Edge between subgraphs
id --> id2
classDef myClass fill:#fef3c7,stroke:#d97706Try in Editor →Conclusion
Subgraphs transform flat, cluttered flowcharts into structured architecture diagrams. They're the bridge between "a bunch of nodes" and "a readable system overview." Master the basics — grouping nodes, connecting subgraphs, and using per-group directions — and your Mermaid diagrams will communicate architectures that anyone on your team can understand at a glance.
Start with a single subgraph in your next diagram to group related services, and build from there.