Mermaid.js State Diagram Syntax Guide

What is a State Diagram?

A State Diagram (also known as a Statechart) is a behavioral UML diagram that models the finite lifecycle of a single object or subsystem. Recognized as a core UML diagram type, it illustrates the discrete conditions (states) an entity can occupy, the external events or triggers that force a shift between those conditions (transitions), and the conditional rule forks that alter execution pathways. This mapping is essential for tracking complex object lifecycles, such as an order’s progression from fulfillment to delivery, a user session timeout sequence, or an embedded hardware switch loop.

With Mermaid.js, you can define your reactive state machines using a declarative, text-driven schema. The parsing engine automatically calculates optimal layout spacing, handles recursive looping arrows, and scales state container boundaries smoothly.

Core Syntax Guide: Elements and Constructs

To design an accurate, standards-compliant UML state diagram in Mermaid, you must master entry/exit markers, transition strings, composite nesting, and conditional choice blocks.

1. Defining Entry, Exit, and Standard States

You initialize a state canvas on line one using the stateDiagram-v2 keyword. Lifecycles require explicit starting and stopping points, which are represented by a solid circle symbol ([*]):

  • Initial State (Entry): [*] --> StateName (Marks where the lifecycle starts).
  • Terminal State (Exit): StateName --> [*] (Marks where the lifecycle concludes).
stateDiagram-v2
    [*] --> Idle
    Idle --> [*]

2. Configuring Transition Triggers and Event Labels

To map a state change, connect your defined state tokens using a standard arrow line (-->). To document the exact event, API response, or button click that causes this transition, append a colon (:) followed by your descriptive text string:

stateDiagram-v2
    Active --> Suspended : PaymentFailed
    Suspended --> Active : InvoiceSettled

3. Implementing Conditional Choice Blocks

To handle branching evaluation loops, use the <<choice>> stereotype. This creates a clear diamond shape on the canvas that splits a single inbound transition path into multiple distinct outbound paths based on runtime logic checks:

stateDiagram-v2
    state check_status <<choice>>
    [*] --> check_status
    check_status --> PremiumUser : if balance >= 100
    check_status --> StandardUser : if balance < 100

4. Structuring Composite (Nested) States

When modeling a complex system, a single high-level state can contain its own independent inner lifecycle. You can create a nested sub-state layout by defining a parent state followed by a body block wrapped in curly braces:

stateDiagram-v2
    state OrderProcessing {
        [*] --> Packaging
        Packaging --> Labeling
    }

Best Practices for Clean State Machine Layouts

  • Keep State Tokens Short: Use brief CamelCase text strings for your internal state tokens (e.g., AwaitingRefund). If you need a long descriptive title on the canvas, use the state "Descriptive Text Block" as Token syntax to create an explicit alias.
  • Enforce a Single Entry Point: Always start your diagram from a single [*] node. Having multiple starting points can confuse users trying to track the root initialization path of the system.
  • Always Use stateDiagram-v2: Always choose the stateDiagram-v2 keyword over the legacy stateDiagram flag. The v2 rendering engine uses an updated layout algorithm that provides cleaner line routing and better nested box alignments.

Real-World Mermaid.js State Diagram Examples

Example 1: Digital Wallet Transaction Lifecycle (Choice Branches & Failure Loops)

This functional blueprint models the lifecycle of a digital payment transaction, showing how a transaction moves from an initial submission point through a fraud check fork into finalized ledger states.

stateDiagram-v2
    state fraud_check <<choice>>

    [*] --> TransSubmitted
    TransSubmitted --> fraud_check : ExecuteRiskAssessment

    fraud_check --> TransApproved : Risk Score Low
    fraud_check --> TransFlagged : Risk Score Elevated
    
    TransFlagged --> TransApproved : ManualManagerOverride
    TransFlagged --> TransDeclined : SecurityTimeout
    
    TransApproved --> SettlementPending : CommitLedger
    SettlementPending --> TransCompleted : BankSettlementSuccess
    
    TransDeclined --> [*]
    TransCompleted --> [*]

Syntax Breakdown: This workflow utilizes a <<choice>> block to evaluate safety scores right at the start. The transaction transitions along distinct pathways based on these scores, with clear event names (like ExecuteRiskAssessment) documented directly on the transition arrows.

Example 2: E-Commerce Order Fulfillment Pipeline (Composite Nested Systems)

This advanced enterprise blueprint outlines a complete shipping and order management lifecycle, using nested composite blocks to show the internal operations happening within the fulfillment phase.

stateDiagram-v2
    [*] --> OrderPlaced
    
    OrderPlaced --> InFulfillment : PaymentCaptured
    
    state InFulfillment {
        [*] --> ItemPicking
        ItemPicking --> QualityAudit : BatchPicked
        QualityAudit --> SecureBoxPacking : AuditPassed
        SecureBoxPacking --> CarrierManifest Generated : LabelPrinted
    }
    
    InFulfillment --> Shipped : CarrierHandshake
    Shipped --> Delivered : OutForDeliveryConfirmed
    
    Delivered --> [*]

Syntax Breakdown: By wrapping steps inside the state InFulfillment {...} body block, you create a clear structural boundary on the canvas. The engine treats this block as a single consolidated parent state while rendering its internal workflow steps sequentially, making complex multi-layered lifecycles easy to navigate.

Scroll to Top