Mermaid sequence diagram actors and lifelines: messaging patterns
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
actorkeyword 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
- Start with actors on the left, end on the right — usually user/client on the left, external systems on the right.
- Use activation boxes — they make it obvious when actors are blocked or idle.
- Show explicit returns — dashed arrows for responses clarify message direction.
- Keep depth reasonable — if a diagram is deeper than 20 messages, split it into sub-diagrams.
- Use notes to explain branching — alt/else blocks need context; say why you choose each path.
- Name messages descriptively —
POST /api/saveis clearer than justSend.
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
Mermaid loop and alt blocks: conditional flows explained
Sequence diagrams often branch: retries, error handling, happy path vs. exceptions. Learn how to show decision logic with alt, else, and loop blocks — no diagram duplication needed.
State Diagram vs Flowchart in Mermaid: Which to Use
State diagram vs flowchart in Mermaid: when to use each, with side-by-side examples you can edit live. Pick the right diagram for your system design.