BPMN business process modeling with Mermaid diagrams
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:
| Element | Symbol | Meaning |
|---|---|---|
| Start/End | Circle | Beginning or end of a process |
| Activity | Rectangle | A step or task (e.g., "Review application") |
| Decision/Gateway | Diamond | A branching point (yes/no, approval/rejection) |
| Event | Circle with marker | Something external triggers a flow (e.g., "Timer expires") |
| Swimlane | Parallel bars | Responsibility (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-pattern | Problem | Fix |
|---|---|---|
| Too many swimlanes | Diagram becomes unwieldy | Group related roles into one lane |
| Unlabeled decisions | Readers don't know what the condition is | Label each branch (Yes/No, Approved/Rejected) |
| Every micro-step → one node | Diagram has 100+ nodes | Aggregate low-level steps into one activity |
| Missing error paths | Looks like happy-path only | Include rejection, timeout, error, and retry paths |
| Swimlanes with no handoffs | Defeats the purpose of swimlanes | Use swimlanes only when showing responsibility |
| Circular loops with no exit | Process never ends | Add 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
Mermaid syntax mistakes beginners make (and how to fix them)
Learn the 10 most common Mermaid syntax errors, why they happen, and how to avoid them. Debug your diagrams faster.
Gitflow diagram: visualizing release and hotfix workflows
Master Mermaid gitflow diagrams to document release, develop, and hotfix branches. Learn the complete workflow with real examples.