learn-mermaid-with-phoebe / Session 3 of 6
Learn Mermaid with Phoebe · Session 3 of 6

Who calls whom: sequence and state

Flowcharts show structure - what exists and what connects. Today's two diagram types show BEHAVIOR: sequence diagrams for conversations over time, state diagrams for lifecycles. Together they are how you diagram what a system actually does at runtime.

🟡 Moderate Data & AI teams 45 min live + self-study
0-3 · Recap 3-22 · Concepts (live cards) 22-41 · Three demos 41-45 · Q&A
Part 0

Why this session exists

"The dashboard is slow" and "the job keeps retrying" are runtime stories, and Nova's zoned map from Session 2 cannot tell them - it has no concept of time or order. Sequence diagrams add the WHO-calls-whom-WHEN axis; state diagrams add the what-happens-to-one-thing-over-its-life axis. These two carry most incident writeups, design reviews, and debugging conversations you will ever have.

Live - presented in session Self-study - read after class ★ Try it now Every pink diagram block is REAL mermaid, rendered live
★ What you walk out with today Sequence diagram fluency - participants, the arrow vocabulary, activations, notes, autonumber - plus the control blocks (loop, alt, opt, par, critical, break) that express real logic. Then state diagrams: the pipeline-job lifecycle as a proper state machine with a choice point and a composite state. Nova gains its first two runtime artifacts.
Part 1 · covers "Sequence diagram" basics

Sequence diagrams - conversations over time 8 min live

A sequence diagram is a transcript with geometry: participants across the top, time flowing DOWN, every arrow one message. If you can narrate "the dashboard asks the API, the API queries the warehouse...", you can already write one.

Dashboard Query API Warehouse request SQL query rows JSON reply time Solid arrow = request. Dotted arrow = reply. Time only ever flows down.
🔍 Click to zoom - the sequence mental model: lifelines down, messages across, time never goes up.
LiveParticipants, actors, and the arrow vocabulary4 min▶

Declare who is in the conversation first - participant draws a box, actor draws a stick figure for humans. The as keyword gives a short ID a long display name: participant api as Query API. Then every line is from ARROW to: message.

sequenceDiagram
  participant dash as Dashboard
  participant api as Query API
  dash->>api: solid arrowhead - a request
  api-->>dash: dotted arrowhead - the reply
  dash-)api: open arrow - async, no reply expected
  dash-xapi: cross - message that fails or is lost
ArrowDrawsConvention
->>solid line, filled arrowheada request or call
-->>dotted line, filled arrowheadthe reply or response
-)solid line, open arrowheadasync fire-and-forget (events, queues)
-xsolid line, crossa message that fails or is dropped
->solid line, no arrowheadrare - plain association
Two habits that keep big sequences sane Short IDs, long display names (participant dw as Warehouse - you will type dw thirty times). And declare participants in the order you want the columns - declaration order IS the layout.
LiveActivations, notes, autonumber - the Nova example4 min▶

Three finishing touches make a sequence read like documentation instead of scratchpaper. Append +/- to an arrow to activate/deactivate the receiver (the thin "busy bar" on the lifeline), Note over a,b: annotates, and autonumber numbers every message so people can say "step 4 is where it breaks".

sequenceDiagram
  autonumber
  actor ana as Analyst
  participant dash as Dashboard
  participant api as Query API
  participant dw as Warehouse
  ana->>dash: open revenue page
  dash->>+api: GET /metrics/revenue
  api->>+dw: SQL query
  Note over api,dw: reads the marts schema only
  dw-->>-api: result rows
  api-->>-dash: JSON payload
  dash-->>ana: rendered chart
  • Activations stack: ->>+ starts a busy bar on the receiver, the matching -->>- reply ends it. Nested calls nest the bars.
  • Note placement: Note right of x:, Note left of x:, or Note over a,b: spanning two lifelines.
  • autonumber is one word on its own line, right after sequenceDiagram. In an incident review, numbered steps are gold.
Real world

The latency hunt. A team argued for a week about why a dashboard took nine seconds. Someone finally drew the sequence: the API called the warehouse once per widget - twelve times per page load. The diagram made the N+1 pattern visible in thirty seconds. The fix was one batched query; the diagram went into the postmortem.

Part 2 · covers "Sequence diagram: loops, alt, par, critical, break"

Control blocks - logic in the conversation 6 min live

Real conversations branch and repeat. Control blocks wrap a group of messages in a labeled frame: loop for repetition, alt/else for branching, opt for a maybe, par for simultaneous work, critical for must-happen sections, break for bailing out. All of them close with end.

LiveThe block vocabulary + Nova's retry logic4 min▶
BlockMeansShape
loop labelthese messages repeatloop ... end
alt labelmutually exclusive branchesalt ... else ... end
opt labelhappens or not - one optional branchopt ... end
par labelbranches run at the same timepar ... and ... end
critical labelmust complete; options handle troublecritical ... option ... end
break labelflow stops here when this happensbreak ... end

Here is Nova's nightly CRM sync with its real retry logic - a loop around an alt, and a break for the give-up path:

sequenceDiagram
  participant sch as Scheduler
  participant ing as Ingestion
  participant crm as CRM API
  sch->>ing: run nightly sync
  loop up to 3 attempts
    ing->>crm: request export
    alt export ready
      crm-->>ing: file URL
    else not ready yet
      crm-->>ing: 202, retry later
    end
  end
  break still failing after 3 attempts
    ing-)sch: page the on-call
  end
  • Blocks nest freely - the alt lives inside the loop here. Two levels is readable; three is a smell.
  • Labels are conditions: write them as facts a reader can check - "export ready", not "case 1".
Real world

Design reviews love alt blocks. "What happens when the export is NOT ready?" is the question senior engineers always ask. A sequence with an explicit else branch answers it before it is asked - and empty else branches in your draft are a to-do list of error handling you have not designed yet.

Self-studypar and critical - the concurrency blocks2 min read▶

Two blocks you will reach for less often but want on the shelf:

  • par - work happening simultaneously: par load dashboards ... and refresh ML features ... end. Nova's warehouse fan-out (dashboards and feature store both reading after a load) is a natural par.
  • critical - a section that MUST complete, with option branches for what happens on trouble: critical acquire schema lock ... option lock timeout ... end. Perfect for migrations and exactly-once guarantees.

Also worth knowing from the docs: participants can carry clickable links via the link/links statements (menus on the participant box) - same spirit as flowchart click, same host-support caveats. We flag it as a docs lookup rather than core kit.

Part 3 · covers "State diagrams" (stateDiagram-v2)

State diagrams - lifecycles 6 min live

A sequence diagram follows a conversation between many parties. A state diagram follows ONE thing through its life: a pipeline job, an order, a ticket, a model version. Nodes are states (nouns), arrows are transitions (events). If your team argues about "what does 'failed' actually mean", you need one of these.

Sequence = the conversation Dashboard API Warehouse many parties, messages over time State = one thing's life queued running succeeded one job, states as nouns, events as arrows Pick by question: "who talks to whom?" = sequence · "what can happen to it?" = state.
🔍 Click to zoom - two lenses on runtime: the conversation between parties vs the lifecycle of one thing.
LivestateDiagram-v2 - states, transitions, start and end3 min▶

Always use stateDiagram-v2 (the v2 renderer is the current one). [*] is both the entry point and the exit point - direction of the arrow decides which. Transitions take a label after a colon: the EVENT that causes the change.

stateDiagram-v2
  direction LR
  [*] --> queued
  queued --> running : worker picks up
  running --> succeeded : all steps ok
  running --> retrying : transient error
  retrying --> running : backoff elapsed
  running --> failed : fatal error
  succeeded --> [*]
  failed --> [*]
  • States are nouns (queued, running), labels are events (worker picks up). If a state name contains a verb phrase, it is probably a transition in disguise.
  • Long names: state "Waiting for upstream data" as wait gives a readable description to a short ID.
  • direction LR/TB works exactly like flowcharts - lifecycles usually read best LR.
  • Choice points: declare state verdict <<choice>> and fan transitions out of it with condition labels - one decision, many exits. You will see it in Demo 2.
LiveComposite states and notes2 min▶

A composite state is a state with an inner life: state running { ... } opens a block where the sub-states live, with their own [*] entry. From outside, "running" is one box; zoom in and it has extract, transform, load. This is the state-diagram version of a subgraph - and the cure for lifecycle diagrams that mix altitudes.

Notes attach context without adding states:

Patternnote right of quarantined bad rows parked for review, never silently dropped end note
Altitude rule If some states describe the job (queued, failed) and others describe steps inside it (extracting, loading), you are mixing altitudes - push the steps into a composite state and the diagram snaps into focus.
Self-studyConcurrency and the rest of the toolbox2 min read▶
  • Concurrent regions: inside a composite state, a line with just -- splits it into regions that are active at the same time - a job that is simultaneously "processing" and "reporting heartbeats". Rare, but nothing else expresses it.
  • Fork and join: state f <<fork>> and state j <<join>> split one transition into parallel paths and merge them back - the transition-level cousin of concurrent regions.
  • Styling: stateDiagram-v2 supports classDef too, same spirit as Session 2 - one meaning per color still applies.
Real world

The status-field audit. A team drew the state machine for their pipeline's status column and found four states in the database that no code could ever reach, and one transition (failed to succeeded, no retry in between) that should have been impossible but happened weekly. The diagram was 15 lines; the cleanup ticket paid for the session.

Demo 1 of 3 · Nova's first runtime artifact

The nightly sync, end to end ★ 8 min · follow along

We build Nova's full nightly CRM sync as one sequence: scheduler kicks it off, ingestion retries the flaky CRM API, quality checks rule on the batch, and the warehouse receives either data or a quarantine entry. Build it in mermaid.live layer by layer; the finished source is below.

sequenceDiagram
  autonumber
  participant sch as Scheduler
  participant ing as Ingestion
  participant crm as CRM API
  participant qa as Quality checks
  participant dw as Warehouse
  sch->>+ing: run nightly sync
  loop up to 3 attempts
    ing->>crm: request export
    alt export ready
      crm-->>ing: file URL
    else not ready yet
      crm-->>ing: 202, retry later
    end
  end
  ing->>+qa: validate rows
  qa-->>-ing: verdict per batch
  alt verdict is pass
    ing->>dw: load to staging
  else verdict is fail
    ing->>dw: write to quarantine
  end
  Note over ing,dw: nothing is ever dropped silently
  ing-->>-sch: run summary

Declare the five participants first, in column order: sch, ing, crm, qa, dw. Render - five lifelines, no messages, no errors.

Add the happy path only, straight through: kick off, one fetch, one validate, one load, one summary. Get the skeleton right before any logic.

Wrap the fetch in loop up to 3 attempts and split its outcome with alt export ready / else not ready yet. Watch the frames draw themselves.

Split the verdict: a second alt for pass vs fail, load vs quarantine. Notice you now have both alts a reviewer would ask about.

Add the polish layer: autonumber up top, activation +/- on ingestion and quality checks, and the Note over stating the no-silent-drops guarantee.

Read it back as an incident narrative: "at step 6 the CRM returned 202..." - if every step is citable, the diagram is review-ready. Save the share URL.

Layering habit Happy path first, then blocks, then polish. Sequences written top-to-bottom in one pass always need untangling; sequences written in layers rarely do.
Demo 2 of 3

The job lifecycle, as a state machine ★ 7 min · follow along

Same nightly job, different lens: one run's life from queued to its final resting state. We add a choice point for the verdict, and a composite state that opens up "running" to show the steps inside.

stateDiagram-v2
  [*] --> queued
  queued --> running : worker picks up
  state running {
    [*] --> extract
    extract --> transform
    transform --> load
    load --> [*]
  }
  running --> verdict : run finished
  state verdict <<choice>>
  verdict --> succeeded : checks pass
  verdict --> quarantined : data checks fail
  verdict --> retrying : transient error
  retrying --> queued : backoff elapsed
  retrying --> failed : attempts exhausted
  succeeded --> [*]
  quarantined --> [*]
  failed --> [*]
  note right of quarantined
    bad rows parked for review,
    never silently dropped
  end note

Skeleton first: [*] --> queued --> running --> succeeded --> [*], each transition on its own labeled line. The happy path of one job.

Add the trouble states: retrying looping back to queued, failed and quarantined as terminal states with their own --> [*].

Insert the choice: state verdict <<choice>>, route running into it, and fan out three labeled exits. One decision point instead of three arrows tangled off "running".

Open the composite: wrap extract, transform, load inside state running { } with their own [*] entry. The outer diagram stays clean; the detail is there when you zoom.

Add the note on quarantined - the design guarantee this diagram exists to defend. Compare against Demo 1: same system, conversation lens vs lifecycle lens.

Real world

This exact diagram belongs in your pipeline's README next to the status enum. Every state in the diagram should exist in the code, and every state in the code should exist in the diagram - drift in either direction is a bug you can now see.

Demo 3 of 3

Sequence-ify a bug report ★ 4 min · build your own

The highest-value daily use of sequence diagrams: turning a prose incident description into a picture that everyone can point at. Here is your prose - go draw it.

The incident, as reported"Around 2am the dashboard showed stale numbers. Turns out the scheduler kicked off the sync, ingestion asked the CRM API three times and got 'not ready' every time, so it gave up and paged on-call. But the dashboard kept serving yesterday's cache and never told anyone it was stale."

List the participants named in the prose: scheduler, ingestion, CRM API, on-call (an actor), dashboard, and the analyst who saw stale numbers. Declare them in rough left-to-right order of involvement.

Convert each sentence into messages. "Asked three times, got not-ready every time" is a loop with a single outcome - no alt needed, that is the point of this incident.

"Gave up and paged" is a break block with an async -) message to on-call. "Kept serving yesterday's cache" is the dashboard replying to the analyst WITHOUT any upstream call - the silent failure, visible as an arrow that starts and ends downstream.

Add one Note over marking where an alert SHOULD have fired. Congratulations: the fix ticket writes itself from the diagram.

Keep your source - post it in the session channel. Next week we compare how differently people diagram the same prose, which is itself the lesson.

Homework

Try it yourself - this week ◐ 30-45 min total

Source material

Official docs covered

This session teaches the working content of the sequence diagram and state diagram pages at mermaid.js.org (mermaid 11.x). Left with the official docs: sequence box grouping, background highlighting, and the per-diagram config knobs.

✓Sequence: participants, actors, arrows, activationsPart 1 - the daily vocabulary to working depth
✓Sequence: loop, alt, opt, par, critical, breakPart 2 - all six blocks, Nova retry as the worked example
✓Sequence: notes + autonumberPart 1 + Demo 1 - annotation and citable steps
✓State diagrams: stateDiagram-v2 corePart 3 - states, transitions, [*], choice, direction
✓State diagrams: composite states + notesPart 3 + Demo 2 - nested lifecycles done properly
◐Sequence: participant links and menusflagged in Part 2 self-study; syntax is a docs lookup
Check yourself

Three questions before you go 🎯 ◐ 90 seconds

1 · The conventional arrow for a REPLY in a sequence diagram is...

Solid = request, dotted = reply. The dash count carries the meaning - readers decode call vs response before reading any label.

2 · Your flow has one optional step that either happens or does not - no second branch. Which block?

alt is for mutually exclusive BRANCHES; opt is the single maybe. An empty else is a design smell, not a syntax trick.

3 · When does a state earn composite treatment - state running { ... }?

Composites fix altitude mixing: job-level states outside, step-level states (extract, transform, load) tucked inside the phase they belong to.

Session 3 cheat sheet · pin this

Sequence skeletonsequenceDiagram · participant id as Name (actor for humans) · declaration order = column order.
Arrows->> request · -->> reply · -) async fire-and-forget · -x lost/failed. Solid asks, dotted answers.
Activations->>+ activates the receiver, -->>- deactivates. Busy bars nest for nested calls.
Blocksloop · alt/else · opt · par/and · critical/option · break - all close with end. Labels are checkable conditions.
Polishautonumber for citable steps · Note over a,b: for guarantees and context. Layer: happy path, blocks, polish.
State skeletonstateDiagram-v2 · [*] entry/exit · a --> b : event. States are nouns, transition labels are events.
State power toolsstate x <<choice>> for decision fans · state Name { } composite for sub-states · note right of x ... end note.
Which lens?"Who talks to whom?" = sequence. "What can happen to this one thing?" = state. Same system, two runtime stories.