Mermaid flowcharts are perfect when you want diagrams that live next to your code, stay reviewable in git, and can be updated as quickly as your systems change.
This guide skips the “hello world” and focuses on the features that make flowcharts maintainable: subgraphs, reusable styling, clean labels, consistent layout, and patterns you’ll use again and again.
A quick refresher (so the rest makes sense)
Mermaid flowcharts use this basic structure:
flowchart LR(orTD) sets the layout directionA --> Bconnects nodesA[Rectangle],A(Rounded),A{Decision}control shapesA -->|label| Badds edge labels
Example
Source
|
1 2 3 4 5 |
flowchart LR A[Request] --> B{Authorized?} B -->|yes| C[Serve content] B -->|no| D[Redirect to login] |
Rendered
1) Layout control that actually improves readability
Pick a direction intentionally
LR(left-to-right) is great for pipelines and request paths.TD(top-down) is great for decision trees and troubleshooting.
Source
|
1 2 3 |
flowchart TD A[Start] --> B[Step 1] --> C[Step 2] --> D[Done] |
Rendered
Use invisible “spacers” to guide layout
Sometimes you need a little structure without adding meaning.
Source
|
1 2 3 4 5 6 7 8 9 10 11 12 |
flowchart LR A[Ingress] --> B[Service] B --> C[Pod 1] B --> D[Pod 2] %% Spacer to keep things from collapsing X[ ]:::spacer classDef spacer fill:transparent,stroke:transparent,color:transparent; C --- X D --- X |
Rendered
Tip: Treat spacers like CSS hacks—use sparingly, but don’t fear them when they improve clarity.
2) Subgraphs (the feature that keeps big diagrams sane)
Subgraphs let you group related nodes. They’re the key to drawing “real” systems without turning your diagram into spaghetti.
Basic subgraph
Source
|
1 2 3 4 5 6 7 8 9 10 11 12 |
flowchart LR subgraph Edge[Edge Layer] CDN[CDN] --> WAF[WAF] WAF --> ALB[Load balancer] end subgraph App[Application Layer] ALB --> API[API service] API --> Q[Queue] API --> DB[(Database)] end |
Rendered
Subgraphs as “swimlanes”
A clean trick is to use subgraphs as swimlanes for responsibility boundaries: client vs platform vs app.
Source
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
flowchart LR subgraph Client U[User] --> B[Browser] end subgraph Platform B --> CDN[CDN] CDN --> ALB[ALB] end subgraph Service ALB --> API[API] API --> DB[(DB)] end |
Rendered
3) Node shapes and labels that age well
Use shapes to convey meaning
A few conventions that readers learn quickly:
- Rounded
A(Run step)for actions - Diamond
A{Decision?}for branching - Cylinder
A[(DB)]for data stores - Stadium
A([Start])andB([End])for boundaries
Multi-line labels
You can use <br/> inside labels to make long text readable.
Source
|
1 2 3 4 5 |
flowchart TD A[Deploy request<br/>from CI] --> B{Change type?} B -->|config| C[Apply config<br/>and reload] B -->|binary| D[Roll service<br/>instances] |
Rendered
Tip: Prefer short node text + edge labels over giant paragraphs in a single node.
4) Link types: solid, dotted, thick, and “not really a dependency”
Mermaid supports different link styles that you can use to communicate strength or meaning.
-->normal flow-.->optional / async / “may happen”==>emphasis / strong coupling
Source
|
1 2 3 4 5 |
flowchart LR A[API] --> B[DB] A -.-> C[Metrics] A ==> D[Payment processor] |
Rendered
5) Styling with classDefs (so diagrams look consistent across your blog)
If you only do one “advanced” thing, do this: define a small style palette and reuse it.
A small, reusable style set
Source
|
1 2 3 4 5 6 7 8 9 10 11 |
flowchart LR classDef edge fill:#eef,stroke:#446,stroke-width:1px; classDef compute fill:#efe,stroke:#464,stroke-width:1px; classDef data fill:#fee,stroke:#644,stroke-width:1px; classDef danger fill:#fdd,stroke:#a33,stroke-width:2px; CDN[CDN]:::edge --> ALB[Load balancer]:::edge ALB --> API[API service]:::compute API --> DB[(Database)]:::data API --> ERR[Error path]:::danger |
Rendered
Apply classes later (cleaner for big diagrams)
When diagrams grow, it’s often clearer to define nodes first, then apply classes.
Source
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
flowchart LR classDef edge fill:#eef,stroke:#446; classDef compute fill:#efe,stroke:#464; classDef data fill:#fee,stroke:#644; CDN[CDN] --> ALB[Load balancer] ALB --> API[API] API --> DB[(DB)] class CDN,ALB edge; class API compute; class DB data; |
Rendered
6) Label edges like you mean it
Edge labels are how you keep nodes short while still conveying meaning.
Source
|
1 2 3 4 5 6 |
flowchart TD A[Client] -->|HTTPS 443| B[CDN] B -->|cache miss| C[Origin] C -->|SQL| D[(DB)] C -->|timeout| E[Fallback] |
Rendered
Tip: If every edge label is “calls”, remove edge labels entirely. Label only what differentiates the link.
7) Clickable diagrams (turn a diagram into navigation)
If your renderer supports it, Mermaid can attach links to nodes.
Source
|
1 2 3 4 5 6 7 8 |
flowchart LR A[Runbook] --> B[Restart service] A --> C[Scale out] click A "https://example.com/runbook" "Open the runbook" click B "https://example.com/restart" "Restart steps" click C "https://example.com/scaling" "Scaling guide" |
Rendered
Replace the example URLs with your own internal documentation links.
8) A real “beyond basics” example: deploy + drain done cleanly
This example combines subgraphs, edge labels, link types, and a small style palette.
Source
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
flowchart LR classDef user fill:#eef,stroke:#446; classDef edge fill:#eef,stroke:#446; classDef compute fill:#efe,stroke:#464; classDef data fill:#fee,stroke:#644; classDef warn fill:#ffd,stroke:#aa7,stroke-width:2px; subgraph Client U[User]:::user --> CDN[CDN]:::edge end subgraph Platform CDN --> ALB[ALB]:::edge ALB -->|new requests| TG1[Target group]:::edge end subgraph Service TG1 --> S1[App v1]:::compute TG1 --> S2[App v1]:::compute S1 --> DB[(DB)]:::data S2 --> DB end CI[CI deploy]:::compute -.->|start rollout| ASG[ASG update]:::compute ASG -.->|add v2| S3[App v2]:::compute ASG -.->|shift traffic| TG1 ASG -.->|drain v1| D{Deregistration<br/>delay}:::warn D -.->|in-flight completes| S1 D -.->|in-flight completes| S2 |
Rendered
9) A checklist for “blog-ready” flowcharts
Before you publish:
- Can a reader understand it in 10 seconds? If not, split it into two diagrams.
- Are your labels consistent? (Requests, events, retries, timeouts)
- Do subgraphs reflect responsibility boundaries? (Client / platform / service)
- Are you using shapes intentionally? (decisions vs actions vs data)
- Are edge labels doing real work? Label the why, not the obvious.
- Do you have a stable style palette? Reuse
classDefnames across posts.
Where to go next
If you found subgraphs and class-based styling useful, the next Mermaid feature to learn is sequence diagrams—they’re often the best way to explain time (retries, backoffs, and latency) without contorting a flowchart.




