Beck
Docs /Draw a sequence diagram

Draw a sequence diagram

A type: sequence document draws the classic interaction diagram — participants across the top, lifelines down, messages in call order — and then does what Mermaid can't: it plays the conversation. Without a flow: block, the message order is the animation; a packet rides each arrow, in order, on loop.

Participants and messages

Declare participants (columns, in order) and messages (rows, in order). Participants take the same fields as architecture nodes — title, kind, icon, accent, subtitle — so a database column can look like a database:

yaml
type: sequence
participants:
  - { id: web, title: Web App, kind: user }
  - { id: api, title: Orders API }
  - { id: db, title: Postgres, kind: db }
messages:
  - { from: web, to: api, label: POST /orders }
  - { from: api, to: db, label: INSERT }
  - { from: db, to: api, label: ok, reply: true }
  - { from: api, to: web, label: 201 Created, reply: true }
beck
POST /ordersINSERTok201 CreatedWeb AppOrders APIPostgres

A few things happened automatically there:

  • Message colors came from the participants: each message tints itself with the accent of the participant doing the work — the receiver of a call, the sender of a reply — so every request/response pair shares one hue. An explicit color: on a message wins.
  • Replies (reply: true) render dashed with an open arrowhead and a quieter label, so request/response pairs read at a glance.
  • Activation bars grew on the receivers: a message starts a bar when a later reply from that receiver back to the sender closes it. Nested request/reply pairs nest their bars. Set activate: false on a message to suppress its bar, or activate: true to force one without a matching reply.
  • The story dims and reveals. With the derived animation, everything starts faded; each message row lights up as its packet fires, activation bars brighten while their participant works, and the whole conversation fades back down before the loop restarts. A hand-written flow: (or animate: false) renders everything at full strength instead.

Self-messages and sections

A message from a participant to itself draws a small loop. A list entry of - section: <label> opens a tinted, dashed band around every message until the next section (or the end) — use it to chapter a long interaction. Give it an accent to color the band and its floating label (- { section: Payment, accent: info }); each section also becomes a phase the animation can seek to and lights up as its chapter begins:

yaml
type: sequence
participants:
  - { id: web, title: Web App, kind: user }
  - { id: api, title: Orders API }
  - { id: pay, title: Payments, icon: lock, accent: info }
messages:
  - { from: web, to: api, label: POST /orders }
  - { from: api, to: api, label: validate cart }
  - { section: Payment, accent: info }
  - { from: api, to: pay, label: capture }
  - { from: pay, to: api, label: captured, reply: true }
  - { from: api, to: web, label: 201 Created, reply: true }
beck
PAYMENTPOST /ordersvalidate cartcapturecaptured201 CreatedWeb AppOrders APIPayments

Async messages

kind: async renders dashed with an open arrowhead and gives the packet the slow, eased async motion — right for fire-and-forget events and queue deliveries:

yaml
type: sequence
participants:
  - { id: api, title: Orders API }
  - { id: bus, title: Events, kind: queue }
  - { id: mail, title: Mailer, icon: mail }
messages:
  - { from: api, to: bus, label: OrderPlaced, kind: async }
  - { from: bus, to: mail, label: deliver, kind: async }
  - { from: mail, to: mail, label: render template }
beck
OrderPlaceddeliverrender templateOrders APIEventsMailer

Narrate the exchange

Because the derived animation plays the messages in order, a sequence narrates itself with almost no effort: add a note: to any message and Beck shows it as a caption under the diagram just before that message fires. Caption a few key steps to walk a reader through the conversation:

yaml
type: sequence
participants:
  - { id: shopper, title: Shopper, kind: user }
  - { id: api, title: Orders API }
  - { id: pay, title: Payments, kind: external }
  - { id: db, title: Postgres, kind: db }
messages:
  - { from: shopper, to: api, label: POST /checkout, note: The shopper submits their cart to the Orders API. }
  - { from: api, to: pay, label: capture, note: The API asks the payment service to capture the total. }
  - { from: pay, to: api, label: captured, reply: true }
  - { from: api, to: db, label: INSERT order, note: "With funds secured, the order is written to Postgres." }
  - { from: db, to: api, label: ok, reply: true }
  - { from: api, to: shopper, label: 201 Created, reply: true }
beck
POST /checkoutcapturecapturedINSERT orderok201 CreatedShopperOrders APIPaymentsPostgresThe shopper submits their cart to the Orders API.The API asks the payment service to capture the total.With funds secured, the order is written to Postgres.

Notes only drive the derived flow — if you script a flow: yourself, narrate it with narrate steps instead. Pace or disable the captions with meta.narrate. See Narrate the story for the full picture.

Scripting the animation

The derived flow (one packet per message, in order) is usually what you want. To take over, add a flow: block exactly as in any other Beck diagram — status, working, fail, and friends all work on participants. See Animate the flow.


Full field tables: participants and messages in the YAML schema. Generating one from C#: SequenceDiagramBuilder.