All posts
MermaidSequence DiagramsArchitectureAPI Design

Mermaid sequence diagram actors and lifelines: messaging patterns

6 min readThe MermaidCreator team

A sequence diagram shows how different parts of a system talk to each other over time. Unlike flowcharts (which show logic), sequence diagrams emphasize ordering, direction, and responsibility. Understanding actors, lifelines, and message types is key to designing interactions that work — especially for APIs, microservices, and distributed systems.

Actors and lifelines: the fundamentals

An actor is a participant in the sequence — a user, a service, a database, an external API. An lifeline is the vertical dashed line below each actor that shows the actor's timeline. A message is an arrow from one lifeline to another, representing a function call, HTTP request, event, or any other interaction.

sequenceDiagram
    actor User
    participant Frontend
    participant Backend
    participant Database

    User->>Frontend: Click "Submit"
    activate Frontend
    Frontend->>Backend: POST /api/save
    activate Backend
    Backend->>Database: INSERT record
    activate Database
    Database-->>Backend: OK
    deactivate Database
    Backend-->>Frontend: 200 OK
    deactivate Backend
    Frontend-->>User: Show success
    deactivate Frontend

Key elements:

  • Actors appear as stick figures (the actor keyword in Mermaid).
  • Participants are boxes (services, systems).
  • Solid arrows (->>) are synchronous messages (I wait for a response).
  • Dashed arrows (-->>) are returns (a response coming back).
  • Activate/deactivate boxes show when an actor is busy.

Actor roles: choosing the right notation

Actors represent different roles in your system. Choose wisely:

  • actor — a human user, external system, or any role outside your system. Use for end-users, third-party APIs, manual steps.
  • participant — an internal service, module, or component. Use for your frontend, backend, database, microservices.
sequenceDiagram
    actor Customer
    participant Web
    participant PaymentService
    participant Stripe
    participant Database

    Customer->>Web: Enter card details
    Web->>PaymentService: POST /charge
    PaymentService->>Stripe: Charge card
    Stripe-->>PaymentService: Success
    PaymentService->>Database: Save transaction
    Database-->>PaymentService: OK
    PaymentService-->>Web: 200 OK
    Web-->>Customer: "Payment received"

The diagram clearly shows that the customer is external, Stripe is a third-party service, and everything else is internal.

Message types: synchronous vs. asynchronous

Synchronous (->>): The sender waits for a response. Use for function calls, HTTP requests, or any "blocking" interaction.

Asynchronous (->): The sender doesn't wait. Use for events, webhooks, or messages in a queue.

Return (-->>): An explicit response. Use when you want to show what comes back.

Self-call (->>): An actor calling itself. Use to show internal logic or recursion.

sequenceDiagram
    participant Client
    participant API
    participant Queue
    participant Worker

    Client->>API: Request /process
    activate API
    API->>Queue: Enqueue task (async)
    deactivate API
    API-->>Client: 202 Accepted
    
    Queue->>Worker: Send task
    activate Worker
    Worker->>Worker: Do heavy work
    Worker-->>Queue: Done
    deactivate Worker

Here, the API doesn't wait for the worker; it returns immediately with a 202 (Accepted) status. The worker processes asynchronously.

Activation and deactivation: showing who's busy

Use activate and deactivate to show the period when an actor is actively processing:

sequenceDiagram
    participant Client
    participant Cache
    participant Database

    Client->>Cache: GET key
    activate Cache
    
    Note over Cache: Check if exists
    
    alt Cache hit
        Cache-->>Client: Return value
    else Cache miss
        Cache->>Database: SELECT *
        activate Database
        Database-->>Cache: Result set
        deactivate Database
        Cache-->>Client: Return value
    end
    
    deactivate Cache

Activate/deactivate boxes make it clear when actors are blocked waiting for something, versus when they're idle. This is especially useful in showing bottlenecks.

Conditionals: alt, else, and opt

Use alt (if/else) and opt (optional) blocks to show branching logic:

  • alt ... else — if this path, else that path.
  • opt — this might happen, or it might not.
  • par — parallel execution (actors act simultaneously).
  • loop — repeat this sequence.
sequenceDiagram
    participant User
    participant App
    participant API
    participant Cache

    User->>App: Load profile
    activate App
    App->>Cache: GET user:123
    activate Cache
    
    alt Cache hit
        Cache-->>App: User data
        deactivate Cache
        opt Stale data?
            App->>API: GET /users/123
            activate API
            API-->>App: Fresh data
            deactivate API
        end
    else Cache miss
        App->>API: GET /users/123
        activate API
        API-->>App: User data
        deactivate API
        App->>Cache: SET user:123
        activate Cache
        Cache-->>App: OK
        deactivate Cache
    end
    
    App-->>User: Show profile
    deactivate App

This shows a cache-with-fallback pattern: try cache, fall back to API if miss, optionally refresh if stale.

Parallel interactions: par blocks

When multiple actors communicate at the same time, use par:

sequenceDiagram
    participant Server
    participant ServiceA
    participant ServiceB
    participant ServiceC

    Server->>ServiceA: Fetch data A
    Server->>ServiceB: Fetch data B
    Server->>ServiceC: Fetch data C

    par
        ServiceA-->>Server: Result A
    and
        ServiceB-->>Server: Result B
    and
        ServiceC-->>Server: Result C
    end

    Server->>Server: Aggregate results
    Server-->>Server: Return combined data

This shows that the server fires three requests in parallel and waits for all three to complete (a common pattern in API aggregation).

Note annotations: explaining behavior

Use Note over and Note right/left to add explanatory text:

sequenceDiagram
    participant Browser
    participant Server
    participant Cache

    Browser->>Server: GET /api/users
    activate Server
    
    Note right of Server: Check Redis cache first
    
    Server->>Cache: GET users
    activate Cache
    Cache-->>Server: Null
    deactivate Cache
    
    Note right of Server: Cache miss, query database
    
    Server->>Server: Query DB
    Server->>Cache: SET users (TTL 300s)
    activate Cache
    Cache-->>Server: OK
    deactivate Cache
    
    Server-->>Browser: 200 + data
    deactivate Server

Notes help readers understand the "why" behind each step.

Common sequence diagram patterns

Request-response with timeout

sequenceDiagram
    participant Client
    participant API
    participant Timeout

    Client->>API: POST /slow-operation
    activate API
    
    par
        API->>API: Processing
    and
        Timeout->>API: Timeout after 30s
    end
    
    deactivate API
    API-->>Client: 504 Gateway Timeout

Retry logic

sequenceDiagram
    participant Client
    participant API
    
    loop Retry up to 3 times
        Client->>API: Request
        activate API
        
        alt Success
            API-->>Client: 200 OK
            deactivate API
        else Failure
            API-->>Client: 5xx Error
            deactivate API
            Note over Client: Wait and retry
        end
    end

Microservice choreography

sequenceDiagram
    participant User
    participant OrderService
    participant InventoryService
    participant PaymentService
    participant NotificationService

    User->>OrderService: Place order
    activate OrderService
    
    OrderService->>InventoryService: Reserve stock
    activate InventoryService
    InventoryService-->>OrderService: Reserved
    deactivate InventoryService
    
    OrderService->>PaymentService: Charge card
    activate PaymentService
    PaymentService-->>OrderService: Charged
    deactivate PaymentService
    
    OrderService->>NotificationService: Send confirmation
    activate NotificationService
    NotificationService-->>OrderService: Sent
    deactivate NotificationService
    
    OrderService-->>User: Order confirmed
    deactivate OrderService

Best practices for sequence diagrams

  1. Start with actors on the left, end on the right — usually user/client on the left, external systems on the right.
  2. Use activation boxes — they make it obvious when actors are blocked or idle.
  3. Show explicit returns — dashed arrows for responses clarify message direction.
  4. Keep depth reasonable — if a diagram is deeper than 20 messages, split it into sub-diagrams.
  5. Use notes to explain branching — alt/else blocks need context; say why you choose each path.
  6. Name messages descriptivelyPOST /api/save is clearer than just Send.

When to use sequence diagrams

  • API design — show request/response flows before coding.
  • Microservice interactions — trace a request across multiple services.
  • Authentication flows — OAuth, JWT, multi-factor authentication.
  • Distributed system debugging — reason about order of operations.
  • Documentation — help new team members understand how systems talk.

FAQ

Should I show every HTTP header and query parameter? No. Keep messages high-level (e.g., POST /api/users instead of POST /api/users?format=json&fields=name,email). Details belong in API docs.

How do I represent a timeout or error? Use an alt block with error messages, or add a dashed arrow labeled with the error code (e.g., -->> Client: 500 Error).

Can I nest sequence diagrams? Mermaid doesn't support nested diagrams directly, but you can create multiple diagrams — one for the high-level flow, one for each critical sub-flow.

Try designing an API flow in the visual editor at /playground — draw the interaction, refine the message ordering, then export the code to your API documentation.

Related posts