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 --> C
Try 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 --> B
Try 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]
    end
Try 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 --> be
Try 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 --> Gateway
Try 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 --> Internet
Try 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 --> API2
Try 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 --> Queue
Try 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 --> NotifSvc
Try 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:#14532d
Try 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:2px
Try 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 --> B
Try 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
end
Try in Editor →
%% CORRECT
flowchart TD
    subgraph A
        Node1 --> Node2
    end
    subgraph B
        Node3
    end
Try 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)]
    end
Try in Editor →
%% CORRECT — unique IDs
flowchart TD
    subgraph Frontend
        feReact[React] --> feRedux[Redux]
    end
    subgraph Backend
        beExpress[Express] --> beDB[(DB)]
    end
Try 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]
    end
Try 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
    end
Try 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:#d97706
Try 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.

Try subgraphs in our free Mermaid Live Editor →