How to Draw a Sequence Diagram: Complete Guide | text2diagram
Learn how to draw a sequence diagram with 5 core elements, 5 message types, and 10 practical rules — then let text2diagram's AI turn plain English into a Mermaid sequence diagram.
1. What is a sequence diagram?
A sequence diagram is a visual description of how a group of actors exchange messages over time. It shows who calls whom · in what order · with what response — nothing more, nothing less. If a flowchart is about the shape of a process, a sequence diagram is about the dialogue between the participants who carry it out.
Sequence diagrams originated in the UML family and remain the industry standard for documenting API integrations, authentication handshakes, distributed system interactions, and any interaction where ordering matters. Time flows top-to-bottom; participants line up left-to-right as vertical lifelines; every message is a labeled arrow between two lifelines at a specific vertical position.
Two properties make sequence diagrams uniquely valuable:
- Every arrow has a source, a target, and a payload. You can't hand-wave "and then the backend does something" — the diagram forces you to name the sender, the receiver, and what was sent. - Vertical position encodes time. Two arrows on the same lifeline mean the second happens after the first. This is why a sequence diagram can convey timing constraints that a flowchart cannot.
2. Why draw a sequence diagram?
Three core reasons — each addresses a real pain in day-to-day API / distributed-system work:
- Force explicit ownership of each step. Every arrow demands a named source and target. Fuzzy hand-offs like "the system publishes an event" stop being fuzzy the moment they become
OrderService -->> Kafka: OrderPlaced. - Expose ordering assumptions. Race conditions, missing acks, silent retries all become visible when the timing is drawn. Two arrows on the same lifeline with no return in between? You may have accidentally invented an async call.
- Bridge design and code review. A senior engineer can walk a sequence diagram in a review meeting in 3 minutes; walking the equivalent 200 lines of Python takes 30. The diagram becomes the source of truth against which the code is judged.
On top of the three "why"s, a well-drawn sequence diagram delivers three concrete benefits:
Kills whiteboard debates about async vs sync. Solid arrows are synchronous, dashed arrows are returns, open triangles are async. The syntax itself settles the argument — no more "wait, does that call block?" during design review.
Catches missing failure paths early. Every arrow that has no matching return, every alt block without an else branch, every loop without a termination condition — all visible in the picture. Cheaper to fix in the diagram than in production.
Speeds up onboarding for API integrators. External integrators reading your OAuth or webhook docs pick up the flow 5× faster from one sequence diagram than from a wall of prose. Stripe, Auth0, Google — every serious API docs page ships sequence diagrams for exactly this reason.
3. Five core elements
A sequence diagram uses a small, disciplined vocabulary. Master these five and you can read 95% of the sequence diagrams you'll ever encounter:
| Participant | The top-of-diagram rectangle representing an actor: a user, a service, a queue, a database, an external API. Each participant has a vertical lifeline dropping down from its rectangle. Aliases keep the diagram narrow: participant db as PostgreSQL. |
| Lifeline | The vertical dashed line under each participant. Time flows downward along the lifeline. Two events on the same lifeline mean the lower one happens later. |
| Message | A labeled arrow between two lifelines. The message name goes on the arrow, describing what is being sent — a method call, an HTTP request, a queue payload. Five arrow styles exist (see §4). |
| Activation | The narrow vertical rectangle that appears on a lifeline while that participant is actively doing work. Drawn by activate X and deactivate X, or auto-generated with the + / - message prefixes (A ->> +B opens, B -->> -A closes). Optional but highly recommended — it makes concurrency obvious. |
| Note & Fragment | Notes are freeform annotations attached to one or more lifelines (Note right of A: retry on 5xx). Fragments group messages under a control-flow rule — alt / else, opt, loop, par, critical, break. Fragments are what give sequence diagrams their expressive power (see §7). |
That's the entire visual grammar. Every sequence diagram — from a two-line "user logs in" example to a fifty-message saga orchestration — is composed of these five nouns.
4. Five message (arrow) types
Mermaid supports five arrow syntaxes, each carrying a distinct meaning. Getting the arrow right is 80% of getting the diagram right:
->> Sync request | Solid line with filled arrowhead. The caller blocks until a response comes back. Use for HTTP request/response, RPC, method invocation. The overwhelmingly most common arrow type — reach for this by default. |
-->> Return | Dashed line with filled arrowhead. The response coming back from a prior sync call. Pair every ->> with a -->> unless you deliberately want to show a fire-and-forget. |
-) Async send | Solid line with open arrowhead. Caller does not wait — the message goes into a queue, an event bus, or a WebSocket. Ideal for Kafka publishes, WebSocket pushes, SNS notifications. |
-> Self-message | Any arrow style where source and target are the same participant. Represents internal work — a service calling its own helper method. Renders as a small loop-back on the lifeline. Use sparingly; too many self-messages usually mean you should factor out a helper participant. |
x Lost / found message | Solid line ending in an X (->x for lost, x-> for found). Represents a message that never reaches its target, or arrives from an unknown source. Used to document error paths, dropped connections, or spontaneous events. Advanced use — you'll rarely need it. |
5. Mermaid sequence syntax essentials
Mermaid's sequence syntax is small enough to fit on a postcard. The first line must be sequenceDiagram, and every subsequent line is either a participant declaration, a message, or a fragment marker:
sequenceDiagram
autonumber
actor User
participant Web as Web App
participant API as API Server
participant DB as PostgreSQL
User->>Web: click Login
Web->>+API: POST /auth (email, password)
API->>+DB: SELECT user WHERE email=?
DB-->>-API: user row + password_hash
API->>API: bcrypt.compare(pw, hash)
alt password matches
API-->>-Web: 200 OK + JWT
Web-->>User: redirect to /dashboard
else password wrong
API-->>Web: 401 Unauthorized
Web-->>User: show error banner
end
Note right of API: rate-limit: 5 attempts / minSix things worth noting in the code above:
- autonumber prepends 1., 2., 3. to every message — indispensable when you reference messages by number in prose ("in step 4 we…"). Costs nothing, always turn it on.
- actor is used for people (stick-figure icon). participant is used for systems (rectangle). Purely cosmetic, but it helps the reader.
- as gives a short alias. Use it when the display name would make lifelines too wide (participant DB as PostgreSQL).
- The + / - after the arrow (e.g. ->>+API) auto-activates the target when it starts working and deactivates when it responds. Cleaner than manual activate / deactivate.
- alt / else / end is the branching fragment. See §7 for the full fragment catalog.
- Note right of X attaches a note to a lifeline. Use Note over X, Y to span multiple lifelines.
6. Ten rules for readable sequence diagrams
The following ten rules come from reviewing hundreds of production sequence diagrams and observing what makes readers understand them in 30 seconds vs 5 minutes:
- One diagram, one story. Every sequence diagram should answer a single question — "how does login work?", "what happens when payment fails?". If you catch yourself drawing two scenarios in one diagram, split it.
- 5-9 participants max. More and the diagram becomes a spaghetti wall. Aggregate related components ("Data Layer" instead of Redis + Postgres + Elasticsearch) or split into multiple diagrams.
- Order participants left-to-right by call frequency. The participant that initiates the most calls goes on the left. This minimizes long horizontal arrows crossing the diagram.
- Pair every
->>with a-->>. Missing return arrows are the #1 reader confusion — is the caller waiting or moving on? Explicit returns kill the ambiguity. Only omit for genuine fire-and-forget (use-)). - Label with verbs and payloads, not method names.
->> API: POST /login (email, pw)beats->> API: login(). The reader wants to know what was sent, not just the function name. - Use
autonumber. Free numbering makes every message referenceable in prose, tickets, and code comments ("step 3 in the login sequence"). Never a downside. - Activate for compute; skip for straight-through. Show activation bars when a participant does non-trivial work between receiving and responding (database query, external call). Don't clutter with activations for pure pass-through routers.
- Time flows down, only down. Never draw an arrow that goes upward. If A responds to B, put A's response below B's request. Upward arrows read as time-travel and confuse everyone.
- One alt branch per outcome — always with an else. If you draw an
alt successblock, you owe the reader anelse failureblock. Single-branch alt is code smell; useoptfor optional-only paths. - Notes for the why, arrows for the what. A well-placed note (
Note right of API: retry on 5xx up to 3×) tells the reader why something happens without cluttering the arrow labels. Keep arrows short; put context in notes.
7. Advanced: fragments (alt / opt / loop / par / critical / break)
Fragments are what let sequence diagrams express control flow — branching, looping, parallelism — without turning into flowcharts. Six fragment types cover every real-world case:
alt / else | If / else / else if. Draw when the flow branches on a condition. Every branch runs mutually exclusively. Always terminate with end. Nesting is legal but keep to 2 levels max — deep nesting quickly becomes unreadable. |
opt | Optional block. For "this may or may not happen" — no else branch. Common uses: cache lookups, logging side effects, optional retries. |
loop | Repeated messages. Body executes 0-N times. Always write the termination condition in the loop label (loop until success beats bare loop) — otherwise readers assume infinite loop. |
par / and | Parallel execution. Two or more branches happen simultaneously. Use for concurrent API calls, Promise.all, fanout patterns. Each branch is separated by and. The diagram makes concurrency graphically obvious. |
critical / option | Critical section with alternates. For "this must happen, but here are the fallbacks". Common in error-handling flows — try primary path, fall back to cached data, fall back to error page. Newer syntax; not all renderers support it — Mermaid does. |
break | Early termination. Marks a break-out from a longer sequence — e.g., "if authentication fails here, skip everything below". Renders as a distinctive frame around the block. |
8. Three real-world examples
The best way to internalize sequence diagrams is to read a few from real systems. Below are three canonical patterns with their Mermaid source — you can click "Try it in text2diagram →" under each to generate them from a plain-English description.
Example 1 — OAuth 2.0 authorization code flow
The classic three-party dance: user, client app, auth server. Note the two round-trips through the user's browser — this is what makes OAuth non-trivial to explain in prose.
sequenceDiagram
autonumber
actor U as User
participant C as Client App
participant AS as Auth Server
participant RS as Resource API
U->>C: click "Log in with X"
C->>U: 302 redirect to AS/authorize
U->>AS: GET /authorize (client_id, scope)
AS-->>U: login form
U->>AS: submit credentials + consent
AS->>U: 302 redirect back with code
U->>C: GET /callback?code=abc
C->>+AS: POST /token (code, client_secret)
AS-->>-C: access_token + refresh_token
C->>+RS: GET /user (Bearer access_token)
RS-->>-C: user profile JSON
C-->>U: render dashboardExample 2 — Distributed saga with compensation
The saga pattern is how microservices coordinate a transaction without a 2PC coordinator. Every step publishes an event; every failure triggers a compensating action. Sequence diagrams shine here because the ordering of events is the entire point.
sequenceDiagram
autonumber
participant O as OrderService
participant P as PaymentService
participant I as InventoryService
participant B as EventBus
O->>+B: publish OrderCreated
B-)P: OrderCreated
P->>P: charge card
alt charge succeeds
P-)B: publish PaymentCharged
B-)I: PaymentCharged
I->>I: reserve stock
alt stock available
I-)B: publish StockReserved
B-)O: StockReserved
O->>-O: mark order Confirmed
else stock unavailable
I-)B: publish StockFailed
B-)P: StockFailed
P->>P: refund card (compensation)
P-)B: publish PaymentRefunded
B-)O: PaymentRefunded
O->>O: mark order Cancelled
end
else charge fails
P-)B: publish PaymentFailed
B-)O: PaymentFailed
O->>O: mark order Cancelled
endExample 3 — WebSocket chat with read receipts
Real-time patterns are where async messages (-)) earn their keep. Client A sends, server persists, server pushes to Client B, Client B sends back a receipt. No single call blocks; every arrow is fire-and-forget over an open socket.
sequenceDiagram
autonumber
participant A as Client A
participant S as Server
participant DB as MessageDB
participant B as Client B
A-)S: WS send: hello
S->>+DB: INSERT message (from=A, to=B)
DB-->>-S: message_id
S-)B: WS push: new message
B->>B: render + auto-mark-read
B-)S: WS ack: read_receipt(message_id)
S->>+DB: UPDATE message SET status=read
DB-->>-S: ok
S-)A: WS push: read_receipt9. Common mistakes to avoid
After a few hundred code reviews, the same six mistakes keep appearing:
- Drawing a flowchart in disguise. If your "sequence diagram" has diamond decisions and branches that loop back over themselves, you actually wanted a flowchart. Sequence diagrams model interactions between actors, not control flow within one actor.
- Forgetting the return arrow. A
->> API: querywith no follow-up-->> Caller: resultleaves the reader wondering if the caller blocks, times out, or moved on. Explicit returns cost one line and remove all ambiguity. - Alt without else.
alt success ... endwith no failure branch is a code smell — you're implying "nothing happens on failure", which is almost never true in production. Useoptif it really is optional; otherwise write the else. - Too many participants. Ten participants across the top row means fifty possible arrows. If you're above 9, aggregate ("Data Layer" over Redis + Postgres) or split into two diagrams (one for the happy path, one for the error path).
- Backward arrows. Never draw an arrow that points upward or that resolves above its trigger. Time flows down. Backward arrows read as time-travel and destroy the reader's mental model.
- Solid arrows for async messages. A
->>implies the caller waits. If the actual runtime behavior is fire-and-forget (Kafka publish, WebSocket push, background job enqueue), use-)— the reader will thank you when they hit a race condition.
10. Draw sequence diagrams with text2diagram
Hand-authoring the syntax above is fine once you know it, but the reason text2diagram exists is to compress "describe an API interaction in English → get a Mermaid sequence diagram" into one sentence. Under the hood:
- Router picks sequenceDiagram automatically for language cues like "then", "sends", "responds", "calls" — you don't have to say "make me a sequence diagram". - Semantic Validator enforces the 10 rules from §6 (missing returns, alt-without-else, backward arrows, over 9 participants) before showing you the result. - Repair Loop self-heals Mermaid syntax errors — if the LLM emits an invalid diagram, the loop retries with the parser error injected into the prompt. Production syntactic error rate is under 1%. - Chat mode asks 1-3 clarifying questions when the request is ambiguous. Typical questions for sequence diagrams: "which participant initiates?", "should this call be synchronous or async?", "what's the failure path?".
Two modes to choose from:
- Quick mode — one prompt, one shot. Best when your description is already precise (5 participants or fewer, clear ordering, no branching).
- Chat mode — 1-3 clarifications before drawing. Use for OAuth-scale interactions, saga patterns, anything with error branches. The AI's questions often surface assumptions you'd overlooked.
11. A reusable prompt template
When your interaction is complex, feed the AI a structured template instead of a free-form paragraph. This template covers every real-world case:
Sequence diagram for [scenario name].
Participants:
- [name] ([role], e.g. user / service / queue / db])
- [name] ([role])
- ...
Happy path:
1. [source] -> [target]: [message + payload]
2. [source] -> [target]: [message]
3. ...
Failure paths:
- If [condition]: [alternative sequence]
- If [condition]: [alternative sequence]
Async / concurrent:
- [message A] and [message B] happen in parallel
- [message C] is fire-and-forget (no return expected)
Notes / constraints:
- [participant]: [rate limit / retry policy / timeout]Fill in the bracketed placeholders, paste into text2diagram (Chat mode recommended for anything beyond 6 participants), and you'll get a diagram that passes all 10 §6 rules on the first try — or a Confrontation card asking about the ambiguities.
12. Wrap-up
Sequence diagrams win when the story is about ordering and message-passing between multiple actors. Reach for them for API integrations, authentication handshakes, distributed system flows, WebSocket / streaming patterns, and anywhere you find yourself saying "and then, and then, and then".
Master the five elements (§3), pick the right arrow (§4), keep the participant count in check (§6 rule 2), and always draw the failure path (§9 mistake 3). Everything else is stylistic polish.
For anything larger than a whiteboard sketch, let text2diagram's Chat mode ask its clarifying questions — the questions themselves often improve the design before a single arrow is drawn.
FAQ
Will AI-generated sequence diagrams have errors?
text2diagram has 10 built-in rules and 4 layers of sanitizers that catch the most common issues — missing return arrows, alt-without-else branches, backward-flowing arrows, over 9 participants, self-messages that should be helper participants. A self-healing Repair Loop retries automatically when the Mermaid parser rejects a diagram. In production the syntactic error rate is under 1%. That said, semantic mistakes — the AI misreading whether a call is sync or async, or missing a specific failure branch — do happen; that's what Chat mode is for.
What formats can I export?
SVG (vector, best for embedding in API docs), PNG (raster, best for slides and Notion), Mermaid sequence source (edit in Mermaid Live, or paste into your GitHub README where Mermaid renders natively), and Markdown (with the diagram embedded as a code block). Everything is one click from the preview pane.
When should I choose Chat mode over Quick mode for sequence diagrams?
Rule of thumb: if any of the following are true, use Chat — (1) more than 5 participants, (2) any error / failure branch, (3) any async or fire-and-forget arrow, (4) any parallel
parblock. Chat asks 1-3 clarifying questions before drawing, typically about which participant initiates, whether a specific call is sync or async, and what the failure path is. The questions themselves often improve the design.What's the difference between a sequence diagram and a flowchart?
A flowchart models the shape of a process — decision points, branches, loops — usually within one system or one actor. A sequence diagram models the dialogue between multiple actors over time — who calls whom, in what order, with what response. Test: if you find yourself listing 5 different actors, use a sequence diagram. If you find yourself listing 5 decision points inside one actor's logic, use a flowchart.
Is it free? Any usage limits?
Yes, free to use. Anonymous users get 20 generations per day. Logged-in users get 500 per day. No paywall on any feature.
Can I modify the generated sequence diagram?
Two ways: (1) tweak your prompt and re-generate — the AI keeps state across the conversation, so incremental edits ('actually, also add a retry loop around the payment call') work naturally. (2) When the AI presents its assumptions in a Confrontation card, click NO to reject and re-draw. For hand-level edits, export as Mermaid source and edit directly — the syntax is compact enough that most tweaks are one line.
What other diagrams can text2diagram generate?
Seven core diagram types are supported: flowchart, sequence, class (UML), ERD, state, mindmap, Gantt — plus an architecture-diagram mode for system diagrams (AWS / K8s / microservices). Each type has its own set of rules and sanitizers tuned for that shape family.