All posts
MermaidBusiness ProcessBPMNWorkflowProcess Management

BPMN business process modeling with Mermaid diagrams

7 min readThe MermaidCreator team

Business Process Model and Notation (BPMN) is the standard language for documenting workflows across industries. Unlike flowcharts (which show algorithm steps), BPMN diagrams show business processes—the sequence of activities, decisions, and handoffs that move a business forward.

Mermaid's flowchart and swimlane syntax lets you create BPMN-style diagrams that are clean, version-controllable, and easy to share. Whether you're mapping onboarding, loan approval, supply-chain fulfillment, or incident response, this guide shows you how to apply BPMN principles with Mermaid.

BPMN essentials

BPMN uses five core elements:

ElementSymbolMeaning
Start/EndCircleBeginning or end of a process
ActivityRectangleA step or task (e.g., "Review application")
Decision/GatewayDiamondA branching point (yes/no, approval/rejection)
EventCircle with markerSomething external triggers a flow (e.g., "Timer expires")
SwimlaneParallel barsResponsibility (who performs each step)

Here's a simple BPMN workflow in Mermaid:

flowchart TD
    Start(( Start )) --> Receive["Receive purchase order"]
    Receive --> Validate{Order valid?}
    
    Validate -->|No| Reject["Send rejection email"]
    Validate -->|Yes| Check["Check inventory"]
    
    Check --> Available{Stock available?}
    Available -->|No| Backorder["Place on backorder"]
    Available -->|Yes| Pick["Pick items from warehouse"]
    
    Reject --> End(( End ))
    Backorder --> End
    
    Pick --> Pack["Pack items"]
    Pack --> Ship["Ship to customer"]
    Ship --> Notify["Send tracking info"]
    Notify --> End

This shows: order received → validate → check stock → pick/pack/ship → notify. Each rectangle is an activity; diamonds are decisions.

Real-world example: insurance claim processing

Here's a complete BPMN process for handling insurance claims:

flowchart TD
    Start(( Claim received )) --> Register["Register claim in system"]
    
    Register --> Initial{Initial check:<br/>complete?}
    Initial -->|Incomplete| Request["Request missing documents"]
    Initial -->|Complete| Assess
    
    Request --> Resubmit{Resubmitted?}
    Resubmit -->|No| Reject1["Reject claim"]
    Resubmit -->|Yes| Assess["Assess claim value"]
    
    Assess --> Estimate{Estimated<br/>value OK?}
    Estimate -->|>$10K| Supervisor["Route to supervisor"]
    Estimate -->|≤$10K| Approve
    
    Supervisor --> SuperAuth{Supervisor<br/>approves?}
    SuperAuth -->|No| Reject2["Reject claim"]
    SuperAuth -->|Yes| Approve["Approve claim"]
    
    Approve --> Process["Process payment"]
    Process --> Notify["Notify claimant"]
    Reject1 --> End1(( End ))
    Reject2 --> End2(( End ))
    Notify --> Archive["Archive claim file"]
    Archive --> End3(( End ))

This captures:

  • Initial eligibility check (incomplete → request docs → resubmit cycle)
  • Claim assessment and value estimation
  • Escalation for high-value claims
  • Approval/rejection logic
  • Payment processing and notification

BPMN with swimlanes: responsibilities

Swimlanes show who does what. Each lane represents a role or department:

flowchart TD
    subgraph Customer["🧑 Customer"]
        CStart(( Submit request ))
        CReview["Review quote"]
        CAccept{Accept?}
    end
    
    subgraph Sales["💼 Sales"]
        SReceive["Receive request"]
        SQuote["Create quote"]
        SSend["Send quote"]
        SClose["Close sale"]
    end
    
    subgraph Fulfillment["📦 Fulfillment"]
        FReceive["Receive order"]
        FPick["Pick & pack"]
        FShip["Ship items"]
        FNotify["Send tracking"]
    end
    
    CStart --> SReceive
    SReceive --> SQuote
    SQuote --> SSend
    SSend --> CReview
    CReview --> CAccept
    CAccept -->|Yes| SClose
    CAccept -->|No| CStart
    SClose --> FReceive
    FReceive --> FPick
    FPick --> FShip
    FShip --> FNotify
    FNotify --> CEnd(( Order complete ))

Here:

  • Customer subgraph shows what the customer does (submit, review, accept).
  • Sales subgraph shows sales steps (receive request, create quote, send quote, close sale).
  • Fulfillment subgraph shows fulfillment steps (pick, pack, ship, notify).

Arrows crossing swimlanes show handoffs—when one role passes work to another. This makes it obvious where delays happen and where communication breaks down.

BPMN patterns: common workflows

Sequential steps

The simplest process—one activity follows another, no branching:

flowchart TD
    A(( Start )) --> B["Step 1"]
    B --> C["Step 2"]
    C --> D["Step 3"]
    D --> E(( End ))

Conditional branching (XOR gateway)

One of many paths is taken based on a condition:

flowchart TD
    A(( Start )) --> B["Check status"]
    B --> C{Status?}
    C -->|Active| D["Process"]
    C -->|Inactive| E["Archive"]
    C -->|Pending| F["Wait"]
    D --> G(( End ))
    E --> G
    F --> G

Parallel processing (AND gateway)

Multiple activities happen at the same time:

flowchart TD
    A(( Start )) --> B["Receive order"]
    B --> C["Split into parallel tasks"]
    
    C --> D["Send confirmation email"]
    C --> E["Check payment"]
    C --> F["Check inventory"]
    
    D --> Join["All complete?"]
    E --> Join
    F --> Join
    
    Join --> G["Fulfill order"]
    G --> H(( End ))

Loop (repeat until condition)

An activity repeats until a condition is met:

flowchart TD
    A(( Start )) --> B["Attempt connection"]
    B --> C{Connected?}
    C -->|No| D["Wait 5s"]
    D --> B
    C -->|Yes| E["Proceed"]
    E --> F(( End ))

Anti-patterns in BPMN design

Anti-patternProblemFix
Too many swimlanesDiagram becomes unwieldyGroup related roles into one lane
Unlabeled decisionsReaders don't know what the condition isLabel each branch (Yes/No, Approved/Rejected)
Every micro-step → one nodeDiagram has 100+ nodesAggregate low-level steps into one activity
Missing error pathsLooks like happy-path onlyInclude rejection, timeout, error, and retry paths
Swimlanes with no handoffsDefeats the purpose of swimlanesUse swimlanes only when showing responsibility
Circular loops with no exitProcess never endsAdd a termination condition

Swimlanes vs. subgraphs

Mermaid uses subgraphs for swimlanes. Best practices:

  • Use subgraphs for organizational responsibility: Departments, teams, or external actors.
  • Keep subgraphs focused: One subgraph per actor or role.
  • Cross subgraph lines for handoffs: Arrows that cross lanes highlight communication and delays.
  • Don't nest subgraphs too deeply: Nesting more than one level gets confusing.
flowchart TD
    subgraph Customer["Customer"]
        C1["Place order"]
    end
    subgraph Internal["Internal Team"]
        I1["Receive order"]
        I2["Fulfill order"]
    end
    subgraph Carrier["Shipping Carrier"]
        Sh1["Pick up package"]
        Sh2["Deliver"]
    end
    
    C1 --> I1
    I1 --> I2
    I2 --> Sh1
    Sh1 --> Sh2
    Sh2 --> C2(( Delivered ))

The swimlanes make it clear: customer places order, your team receives and fulfills it, the carrier ships and delivers.

Event-driven BPMN

Mermaid can model events (external triggers) with notes or special circles:

flowchart TD
    A["Request arrives"] --> B{Within<br/>SLA?}
    
    B -->|Yes| C["Process immediately"]
    B -->|No| D["Add to queue"]
    
    Timer["⏱️ Timer expires: 24h"] -.->|triggers| E["Escalate to manager"]
    
    D --> E
    C --> F["Complete"]
    E --> F
    F --> G(( End ))

The dotted line (Timer → Escalate) represents an external event that triggers a branch if the normal flow stalls.

BPMN for incident response

Here's a real-world example—incident management:

flowchart TD
    subgraph Detection["Detection"]
        D1["Alert triggered"]
    end
    
    subgraph Triage["Triage"]
        T1["Assess severity"]
        T2{Critical?}
    end
    
    subgraph Response["Response"]
        R1["Page on-call engineer"]
        R2["Investigate root cause"]
        R3["Implement fix"]
    end
    
    subgraph Recovery["Recovery"]
        Rc1["Deploy fix"]
        Rc2["Verify recovery"]
        Rc3["Notify stakeholders"]
    end
    
    subgraph PostMortem["Post-Mortem"]
        PM1["Document incident"]
        PM2["Schedule review"]
        PM3["Implement preventive measures"]
    end
    
    D1 --> T1
    T1 --> T2
    T2 -->|No| End1(( Log & Close ))
    T2 -->|Yes| R1
    R1 --> R2
    R2 --> R3
    R3 --> Rc1
    Rc1 --> Rc2
    Rc2 --> Rc3
    Rc3 --> PM1
    PM1 --> PM2
    PM2 --> PM3
    PM3 --> End2(( Complete ))

This shows the full incident lifecycle: detection → triage → response → recovery → post-mortem.

FAQ

What's the difference between BPMN and flowchart?
BPMN is for business processes (who does what, when, and why). Flowcharts are for algorithms and logic (if X then Y). BPMN emphasizes swimlanes, roles, and events; flowcharts emphasize decision logic.

Can I use swimlanes for systems instead of people?
Yes. You can label swimlanes as "Frontend," "Backend," "Database," "Message Queue," etc., to show system responsibilities instead of human roles.

How detailed should my BPMN model be?
Start with the happy path (main workflow). Then add key error/rejection paths. If you're capturing every single exception, your diagram becomes unreadable. Two levels of detail is usually right.

Should I use BPMN tools like Visio or draw in Mermaid?
Mermaid is ideal for version control and documentation (commit diagrams like code). Professional BPMN tools (Visio, Lucidchart, draw.io) offer more precise notation and simulation. For teams that work in code/markdown, Mermaid is perfect.

How often should I update my BPMN?
Whenever the process changes significantly. If a step is removed, a decision criteria shifts, or a new swimlane joins the process, redraw the diagram in the same PR or commit. Stale BPMN is worse than no BPMN.

Start modeling your business processes in Mermaid. Clear process flows eliminate confusion, expose bottlenecks, and help teams align on how work gets done. Create your first BPMN diagram in the MermaidCreator editor and share it with your team.

Related posts