Mermaid State Diagram Syntax & Examples
Reference for Mermaid state diagram syntax — stateDiagram-v2, transitions, events, composite (nested) states, fork/join, choice nodes. Copy-paste examples.
Syntax reference, layout guidance, and ready-to-open examples for this diagram type.
A syntax reference for Mermaid's stateDiagram-v2 grammar — read this when you need the exact way to express a transition, a composite state, a choice, or a parallel region, then try the result in the editor.
[*] markerComposite states — nesting state machinesChoice, fork & join — branching & parallelismCommon patterns & gotchasMermaid state diagram constructs, one per row
| Construct | Syntax | Notes |
|---|---|---|
| Diagram keyword | stateDiagram-v2 | Must be the first line, on its own. |
| Start and end | [*] --> Draft Cancelled --> [*] | [*] on the left of an arrow is the entry point; on the right it is a terminal state. |
| Transition | Draft --> Submitted | State names cannot contain spaces — use the alias form below when you need them. |
| Transition label | Draft --> Submitted: submit | The text after the colon is the event or guard that causes the transition. |
| Named state | state "Order Placed" as OrderPlaced | Gives a state a display name with spaces while keeping a short identifier for the arrows. |
| Composite state | state Composite { [*] --> A } | The nested [*] is scoped to the composite, so it marks that sub-machine's own entry rather than the diagram's. |
| Fork, join, choice, history | state Split <<fork>> | Four stereotypes: <<fork>>, <<join>>, <<choice>> and <<history>>. |
| Note | note right of Draft : needs review | left of also works. The note attaches to the named state. |
| Concurrency | -- | A bare double dash inside a composite splits it into regions that run in parallel. |
Syntax reviewed
View Mermaid sourcePlain-text diagram syntax — copy or edit directly.
1stateDiagram-v22 [*] --> Draft3 Draft --> Submitted: submit4 Submitted --> Paid: pay5 Submitted --> Cancelled: cancel6 Paid --> Fulfilled: ship7 Fulfilled --> [*]8 Cancelled --> [*]What is a Mermaid state diagram
A state diagram describes the lifecycle of a single entity as it transitions between modes in response to events. It is a finite-state machine drawn as a graph: nodes are states, edges are transitions, labels on edges name the triggering event. State diagrams are the right shape when the question is what-can-this-entity-do-next-given-where-it-is: order lifecycles (Draft → Submitted → Paid → Fulfilled), feature toggles, UI modes (Idle → Loading → Error / Ready), authentication state (Anonymous → Authenticating → SignedIn). If the question is about call ordering between actors, use a sequence diagram; if it's about steps in a process, use a flowchart.
Basic syntax — stateDiagram-v2 + transitions
Every state diagram starts with stateDiagram-v2 (the v1 syntax exists but v2 is what current Mermaid releases recommend). State names appear bare (Draft, Submitted); transitions use the arrow --> between them: Draft --> Submitted. Event labels go after a colon on the transition: Draft --> Submitted: submit. Mermaid auto-creates states from the transitions — declaring them separately is optional. The diagram reads naturally as "in state Draft, when submit happens, move to Submitted".
stateDiagram-v2— diagram type keyword (always first)A --> B— basic transition from A to BA --> B: event— transition with the triggering event label
Start, end & terminal states — the [*] marker
The special token [*] represents the entry point (when written as the source of a transition) and the exit point (when written as the target). [*] --> Draft declares Draft as the initial state — a small filled circle appears in the rendered diagram. Cancelled --> [*] declares Cancelled as a terminal state. A state machine can have multiple terminal [*] arrows (different outcomes terminate the lifecycle differently); only one entry [*] is standard. Without these markers, the diagram is technically valid but doesn't communicate where the lifecycle begins.
Composite states — nesting state machines
A composite state has its own internal state machine. Declare with state Composite { ... }, listing the inner states and transitions inside the braces. Composite states are useful for modelling multi-stage processes where each stage has its own sub-modes — Checkout might be a composite state containing Address / Payment / Confirmation. Transitions can be entered into and exited from the composite at any level, but the cleanest model is to define a single entry point and a single exit point per composite. Nesting can go several levels deep, though practical readability degrades past two levels.
state Composite { A --> B }— basic composite- Transitions can cross composite boundaries — but ideally enter/exit through a single point
- Composite states render as labelled enclosures around the inner machine
Choice, fork & join — branching & parallelism
Beyond basic transitions, state diagrams support three special node types. Choice nodes (state Pick <<choice>>) are decision points where a guard condition decides the next state — render as a diamond, similar to a flowchart decision. Fork nodes (state SplitPoint <<fork>>) split a single state into multiple parallel sub-states. Join nodes (state JoinPoint <<join>>) re-merge parallel paths back to a single state. Fork/join is the syntax for showing parallel regions inside a state machine — when an entity is simultaneously in two states for two different concerns (e.g. a user account is simultaneously in an EmailVerification state and a PhoneVerification state).
state Pick <<choice>>— guard-based decision (diamond)state SplitPoint <<fork>>— split into parallel sub-statesstate JoinPoint <<join>>— merge parallel paths back
Common patterns & gotchas
Two patterns dominate real state diagrams. Linear lifecycles (Draft → Submitted → Paid → Fulfilled) with optional cancel paths from each state are the most common shape for business workflows. Retry loops (Running → Failed → Queued → Running) with a counter limiting attempts are the second. The most common gotcha: forgetting that state names cannot contain spaces — Order Placed doesn't work; use OrderPlaced or Order_Placed. If you need a display label different from the id, declare separately: state "Order Placed" as OrderPlaced, then use the id OrderPlaced in transitions.
- State names cannot contain spaces — use
OrderPlacedorOrder_Placed - Display labels different from ids:
state "Order Placed" as OrderPlaced [*] -->marks the initial state;--> [*]marks a terminal state