All posts
MermaidMicroservicesArchitectureSystem Design

Mermaid swimlanes for microservices: document service interactions

5 min readThe MermaidCreator team

When you're running microservices, keeping track of who calls whom is critical. Swimlanes in Mermaid flowcharts give you a clean way to show which service owns which steps, making it obvious when you're crossing service boundaries and where bottlenecks or latency risks live.

What are swimlanes?

Swimlanes are vertical lanes in a flowchart, each representing an actor, service, or system. Steps within a lane belong to that actor; arrows crossing lanes show inter-service calls. It's the clearest way to see who does what and when.

Mermaid swimlane syntax

In Mermaid, swimlanes are called subgraphs. Each subgraph gets a direction and a label:

flowchart TD
    subgraph API ["API Gateway"]
        A[Receive request]
        B[Route to service]
    end
    
    subgraph Auth ["Auth Service"]
        C[Validate token]
        D[Return user info]
    end
    
    subgraph DB ["Database Service"]
        E[Query data]
        F[Return result]
    end
    
    A --> C
    D --> B
    B --> E
    F --> A

The subgraph ID ["Label"] syntax creates the swimlane. Everything defined inside (until end) belongs to that swimlane.

Real-world microservices example

Let's trace a typical user authentication and data fetch flow:

flowchart TD
    subgraph Client["Client (Frontend)"]
        A["POST /api/data<br/>(with token)"]
    end
    
    subgraph Gateway["API Gateway"]
        B["Receive request"]
        C["Check rate limit"]
        D{Valid?}
    end
    
    subgraph Auth["Auth Service"]
        E["Validate JWT"]
        F{Token OK?}
    end
    
    subgraph Business["Business Logic"]
        G["Apply filters"]
        H["Sort results"]
    end
    
    subgraph Cache["Redis Cache"]
        I["Check cache"]
        J{Hit?}
    end
    
    subgraph Data["Data Service + DB"]
        K["Query PostgreSQL"]
        L["Return rows"]
    end
    
    A --> B
    B --> C
    C --> D
    D -->|No| A
    D -->|Yes| E
    E --> F
    F -->|Invalid| A
    F -->|Valid| I
    I --> J
    J -->|Yes| G
    J -->|No| K
    K --> L
    L --> G
    G --> H
    H --> A

This diagram shows:

  • Client initiates the request
  • API Gateway does rate-limiting and routing
  • Auth Service validates the token (sync call)
  • Cache is checked before hitting the database
  • Data Service owns the query logic
  • Control flow loops back to the client

Readers can instantly see which services are involved and where the critical path is.

Practical swimlane patterns

Payment processing workflow

flowchart TD
    subgraph Order["Order Service"]
        A["Create order<br/>(pending)"]
        B["Publish order-created<br/>event"]
    end
    
    subgraph Payment["Payment Service"]
        C["Receive event"]
        D["Call Stripe API"]
        E{Charge OK?}
    end
    
    subgraph Notification["Notification Service"]
        F["Receive payment-complete<br/>event"]
        G["Send email receipt"]
    end
    
    subgraph Fulfillment["Fulfillment Service"]
        H["Receive payment-complete<br/>event"]
        I["Schedule shipment"]
    end
    
    A --> B
    B --> C
    C --> D
    D --> E
    E -->|Failed| A
    E -->|Success| F
    E -->|Success| H
    G --> B
    I --> B

This shows event-driven architecture: Order publishes, and multiple services react independently.

Search with multi-service aggregation

flowchart TD
    subgraph API["Search API"]
        A["Parse query"]
        B["Broadcast to<br/>workers"]
        C["Aggregate results"]
    end
    
    subgraph Products["Product Service"]
        D["Search name,<br/>description"]
        E["Return matches"]
    end
    
    subgraph Users["User Service"]
        F["Search by<br/>username, bio"]
        G["Return matches"]
    end
    
    subgraph Articles["Article Service"]
        H["Search by<br/>title, content"]
        I["Return matches"]
    end
    
    A --> B
    B --> D
    B --> F
    B --> H
    E --> C
    G --> C
    I --> C

Shows parallel calls to multiple services and result aggregation.

Best practices for swimlane diagrams

1. One swimlane per service (or team). If Auth is responsible for JWT validation AND password resets, they go in the same lane.

2. Show inter-service calls as arrows crossing boundaries. If an arrow stays within one lane, it's internal logic—no service boundary crossed.

3. Label arrows with the protocol or method. --> |async event| vs --> |REST call| vs --> |gRPC| clarifies the interaction.

4. Use decision nodes (diamonds) sparingly. Too many branches make the diagram hard to follow. Focus on the happy path + 1–2 error cases.

5. Keep it focused. A diagram showing the entire microservices ecosystem becomes a hairball. Zoom in on one user flow or feature.

6. Update it when architecture changes. A stale swimlane diagram is worse than no diagram. Keep it in version control alongside your code (.md file) and update in the same PR as the deployment.

Comparing swimlanes to sequence diagrams

Swimlanes (flowcharts with subgraphs) are better when:

  • You care about which actor performs each step (service ownership is the point).
  • The order of steps matters, but timing doesn't.
  • You want to show conditional logic and branches.

Sequence diagrams are better when:

  • You're showing message interactions over time (request-response roundtrips).
  • Timing and actor lifelines are important.
  • You're documenting a protocol or API contract.

Example: "How does a user sign up?" → swimlanes (who owns the steps). "How does a HTTPS handshake work?" → sequence diagram (order and timing).

Embedding swimlane diagrams

Paste into MermaidCreator's playground to edit and export as PNG or SVG for slides and docs:

```mermaid
flowchart TD
    subgraph ServiceA["Service A"]
        A[Step 1]
    end
    subgraph ServiceB["Service B"]
        B[Step 2]
    end
    A --> B
```

FAQ

Should swimlanes match my org chart? Not necessarily. Services and teams don't always align 1:1. Focus on service boundaries, not reporting structure.

Can I nest swimlanes (a swimlane inside a swimlane)? Mermaid's flowchart subgraphs don't nest well visually. Keep swimlanes flat. For nested structure (service → internal components), use a separate C4 diagram.

How do I show timeouts or error handling? Use labeled edges: --> |timeout| error-handler or --> |retry| same-service.

What if a call is both sync and async? Show the sync call explicitly, then add a dotted arrow for the async callback: --> (sync), -.- (async).

How do I version and maintain swimlane diagrams? Treat them like code: commit to git, review in PRs, update when services change. Store .md files in /docs/architecture/ alongside your service READMEs.

Ready to diagram your microservices? Start in MermaidCreator's playground and export it to your architecture docs.

Related posts