Sequence diagrams
A sequence diagram shows who calls whom, and in what order: a request path, a protocol, a handshake. Each actor is a column with a lifeline, and time runs down the page. The sequence spec reference lists every field and its allowed values.
{ "type": "sequence", "actors": [ {"id": "client", "label": "Client"}, {"id": "gateway", "label": "API Gateway"}, {"id": "auth", "label": "Auth Service"}, {"id": "queue", "label": "Audit Queue"} ], "interactions": [ {"from": "client", "to": "gateway", "label": "POST /login", "style": "solid"}, {"from": "gateway", "to": "auth", "label": "validate credentials", "style": "solid"}, {"from": "auth", "to": "auth", "label": "hash password", "style": "solid"}, {"from": "auth", "to": "gateway", "label": "token", "style": "dashed"}, {"from": "gateway", "to": "queue", "label": "log sign-in", "style": "async"}, {"from": "gateway", "to": "client", "label": "200 OK", "style": "dashed"} ]}

┌────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Client │ │ API Gateway │ │ Auth Service │ │ Audit Queue │
└────────┘ └──────────────┘ └──────────────┘ └──────────────┘
│ │ │ │
│ │ │ │
├ POST /login ─► │ │
│ ┃ │ │
│ ├ validate credentials ─► │
│ │ ┃ │
│ │ ┃───┐ │
│ │ ┃ │ hash password
│ │ ◄───┘ │
│ │ ┃ │
│ ◄╌╌╌╌╌╌╌╌ token ╌╌╌╌╌╌╌╌┤ │
│ ┃ │ │
│ ┠────────────── log sign-in ──────────────▷
│ ┃ │ │
◄╌╌ 200 OK ╌╌╌╌┤ │ │
┃ │ │ │
┌────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Client │ │ API Gateway │ │ Auth Service │ │ Audit Queue │
└────────┘ └──────────────┘ └──────────────┘ └──────────────┘
Actors and their order
Section titled “Actors and their order”Actors are drawn left to right in the order of the actors array. Put the initiator leftmost,
then the others in order of first appearance, and name them by role (“Auth Service”), not by
technology. A message names its ends by actor id, so give each actor a short id.
Interaction styles
Section titled “Interaction styles”Each interaction has a style:
| Style | Use | Arrow |
|---|---|---|
solid |
a call (the default) | a filled arrowhead |
dashed |
a return | a dashed line |
async |
fire-and-forget: the sender does not wait | an open arrowhead |
In the diagram above, POST /login and validate credentials are solid calls, token and
200 OK are dashed returns, and log sign-in to the queue is async. Interactions are
drawn in array order, top to bottom. Label messages with what happens, not with data or
calls: those raise vague-message-label.
Self-messages
Section titled “Self-messages”When an actor does something internally, make an interaction with the same from and to. It
is drawn as a short loop on that actor’s lifeline: hash password above.
Fragments
Section titled “Fragments”A fragment draws a frame around part of the exchange, with its type in a tab at the top-left
corner and each section’s guard in brackets. The types are alt (if and
else, one section per branch), opt (may happen), loop (repeats), par (happens in
parallel) and break (leaves the sequence). over lists the actors it spans; the frame
also widens to every actor its messages reach.
{ "type": "sequence", "actors": [ {"id": "client", "label": "Client"}, {"id": "api", "label": "API"}, {"id": "db", "label": "Database"} ], "interactions": [ {"from": "client", "to": "api", "label": "place order", "style": "solid"}, {"from": "api", "to": "db", "label": "check stock", "style": "solid"}, {"from": "db", "to": "api", "label": "in stock", "style": "dashed"}, {"from": "api", "to": "db", "label": "reserve items", "style": "solid"}, {"from": "api", "to": "client", "label": "out of stock", "style": "dashed"}, {"from": "api", "to": "db", "label": "log stock miss", "style": "solid"}, {"from": "api", "to": "client", "label": "send receipt", "style": "dashed"}, {"from": "api", "to": "db", "label": "retry write", "style": "solid"}, {"from": "api", "to": "db", "label": "write audit row", "style": "solid"}, {"from": "api", "to": "client", "label": "payment failed", "style": "dashed"} ], "fragments": [ { "type": "alt", "over": ["client", "api", "db"], "sections": [ {"label": "in stock", "start": 2, "end": 3}, {"label": "out of stock", "start": 4, "end": 5} ] }, { "type": "opt", "over": ["api", "client"], "sections": [{"label": "receipt requested", "start": 6, "end": 6}] }, { "type": "loop", "over": ["api", "db"], "sections": [{"label": "up to 3 times", "start": 7, "end": 7}] }, {"type": "par", "over": ["api", "db"], "sections": [{"label": "audit", "start": 8, "end": 8}]}, { "type": "break", "over": ["api", "client"], "sections": [{"label": "payment declined", "start": 9, "end": 9}] } ]}

┌────────┐ ┌──────┐ ┌──────────┐
│ Client │ │ API │ │ Database │
└────────┘ └──────┘ └──────────┘
│ │ │
│ │ │
├── place order ──► │
│ ┃ │
│ ├── check stock ───►
│ │ ┃
╔══ alt [in stock] ══════╪══════════════════╪═════╗
║ │ ◄╌╌╌ in stock ╌╌╌╌╌┤ ║
║ │ ┃ │ ║
║ │ ├─ reserve items ──► ║
║ │ │ ┃ ║
╟╌╌ [out of stock] ╌╌╌╌╌╌╪╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╪╌╌╌╌╌╢
║ ◄╌ out of stock ╌╌┤ │ ║
║ ┃ │ │ ║
║ │ ├ log stock miss ──► ║
╚══════╪═════════════════╪══════════════════╪═════╝
│ │ │
╔══ opt [receipt requested] ══╗ │
║ ◄╌ send receipt ╌╌┤ ║ │
╚══════╪═════════════════╪════╝ │
│ │ │
│ ╔══ loop [up to 3 times] ═══════╗
│ ║ ├── retry write ───► ║
│ ╚══════╪══════════════════╪═════╝
│ │ │
│ ╔══ par [audit] ══════════╪═════╗
│ ║ ├ write audit row ─► ║
│ ╚══════╪══════════════════╪═════╝
│ │ │
╔══ break [payment declined] ══╗ │
║ ◄ payment failed ╌┤ ║ │
╚══════╪═════════════════╪═════╝ │
│ │ │
┌────────┐ ┌──────┐ ┌──────────┐
│ Client │ │ API │ │ Database │
└────────┘ └──────┘ └──────────┘
Each section covers interactions by index. Indexes are zero-based, and start and end are
both inclusive: in the spec above, the in stock section is "start": 2, "end": 3, the third
and fourth interactions, and out of stock is "start": 4, "end": 5, the fifth and sixth. The
section’s label is its guard, drawn in brackets. Give every section a guard: an alt section
without one raises unlabeled-alt-section. A fragment’s sections run in order without
overlapping, and two fragments either nest or stay apart: ranges that cross are a validation
error. check reports deep-nesting when a fragment sits more than 3 levels deep.
Activations
Section titled “Activations”An activation bar on a lifeline shows when an actor is busy handling a call, and is drawn by
default. Set "activations": false at the top level for a lighter drawing. Here is the first
diagram again without the bars:
{ "type": "sequence", "actors": [ {"id": "client", "label": "Client"}, {"id": "gateway", "label": "API Gateway"}, {"id": "auth", "label": "Auth Service"}, {"id": "queue", "label": "Audit Queue"} ], "interactions": [ {"from": "client", "to": "gateway", "label": "POST /login", "style": "solid"}, {"from": "gateway", "to": "auth", "label": "validate credentials", "style": "solid"}, {"from": "auth", "to": "auth", "label": "hash password", "style": "solid"}, {"from": "auth", "to": "gateway", "label": "token", "style": "dashed"}, {"from": "gateway", "to": "queue", "label": "log sign-in", "style": "async"}, {"from": "gateway", "to": "client", "label": "200 OK", "style": "dashed"} ], "activations": false}

┌────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Client │ │ API Gateway │ │ Auth Service │ │ Audit Queue │
└────────┘ └──────────────┘ └──────────────┘ └──────────────┘
│ │ │ │
│ │ │ │
├ POST /login ─► │ │
│ │ │ │
│ ├ validate credentials ─► │
│ │ │ │
│ │ ├───┐ │
│ │ │ │ hash password
│ │ ◄───┘ │
│ │ │ │
│ ◄╌╌╌╌╌╌╌╌ token ╌╌╌╌╌╌╌╌┤ │
│ │ │ │
│ ├────────────── log sign-in ──────────────▷
│ │ │ │
◄╌╌ 200 OK ╌╌╌╌┤ │ │
│ │ │ │
┌────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Client │ │ API Gateway │ │ Auth Service │ │ Audit Queue │
└────────┘ └──────────────┘ └──────────────┘ └──────────────┘
Every actor is a column, so width is the limit. Keep to 8 participants or fewer, which is where
seq-too-many-participants fires, and about 6 when the art must fit a terminal. Past that, split
the exchange into focused diagrams, or collapse minor participants into one.
For every field and value, see the sequence spec reference.