Skip to content
MermaidViewer

Start here

What is a mermaid diagram, and when should you write one

People who ask what is a mermaid diagram want a text file that states a claim about a system, plus the picture a renderer makes from that text. The file is the artifact. The picture is the view.

By MermaidViewer editorsUpdated 16 min read

People who ask what is a mermaid diagram want a text file that states a claim about a system, plus the picture a renderer makes from that text. The claim might be "this request takes these branches," or "this row points at that row," or "this object moves from draft to live." The picture is the view. The file is the artifact you review, diff, and keep. If you came here for the library itself, who maintains it and how a renderer is wired, that answer lives on what Mermaid is. This page stays with the diagram.

I care about the split because teams archive the picture and lose the claim. A PNG in a wiki can be lovely and still be three deploys out of date. The text, sitting next to the code, goes stale too. It just goes stale in a diff someone can see. That's the property I want from a diagram. Not beauty. A visible lie.

A diagram is a file with a claim

The file is small. The first meaningful line is a keyword that picks a grammar: flowchart, sequenceDiagram, erDiagram, stateDiagram-v2, and the others indexed on the diagram types page. The lines under the keyword are statements. Each statement should be something you could say in a review and defend. "Unauthenticated requests do not write an audit row." "An order has at least one item." "A refund in review can return to draft." If a line isn't a claim, it's decoration, and decoration is what makes the file hard to update.

One file, or one fenced block, holds one diagram. A second keyword is not a second picture. It's a parse error. I mention that because people learn "a Mermaid diagram" as a vibe and then paste three grammars into one fence. You have three diagrams. Give them three blocks. They are allowed to describe the same feature. They are not allowed to share a keyword.

Ids are for the author. Labels are for the reader. gate{Over 50?} has an id of gate and a label a person can read. When the threshold changes to 20, you change the label. The arrows still point at gate. If you used the sentence as the id, every arrow edits, and the diff hides the actual change. This is the same discipline as naming a function. The cheat sheet lists the shapes and arrows so you don't invent punctuation. It will not choose the claim. You do that.

The renderer reads the keyword, builds a model, and lays out shapes. You don't place the shapes by hand. That's the deal. You give up pixel-perfect control. You get a file that merges. I think that's a good deal for almost every diagram that has to survive a quarter. I think it's a bad deal for a conference poster, where the layout is the product. Don't use this format for the poster. Use it for the spec the poster was supposed to match.

A diagram that parses can still be false. The renderer checks grammar. It does not check your system. I have merged beautiful, valid flowcharts that described a service we had already deleted. Validity is the start of the review, not the end. Read the statements out loud. If you wouldn't say them in the pull request, delete the line.

The kinds you will actually open

There are more diagram types than a design doc needs. The ones I reach for answer different questions, and using the wrong one produces a picture that looks busy and doesn't settle the argument.

A flowchart answers "which way does this go when the answer is no?" It is boxes, decisions, and arrows. It does not care who runs the code. Use it for a policy: refunds, retries, feature flags, the train and eval split. The flowchart type is the syntax when you need a subgraph or a third edge out of a diamond. Most policies fit in one screen without either.

A sequence diagram answers "who calls whom, and what comes back?" Lifelines are the actors. Arrows are the messages. Forks are alt and opt. Use it when a paragraph would say "and then the bank, unless." Don't use it when there is only one actor. A sequence of a function calling itself in a straight line is a flowchart that got dressed up. The sequence type is the reference for arrow shapes. If you only remember one thing, remember that a fork and a maybe are different blocks.

An ER diagram answers "what is stored, and how many?" Crow's feet and foreign keys. It is the wrong picture of a request and the right picture of a migration. A class diagram answers "what are the types in the code, and who holds whom?" Similar boxes, different claims. Methods and inheritance belong on the class diagram. Row counts belong on the ER diagram. I've watched a design review try to pick a foreign key off a class diagram. The class diagram didn't have one. It had a field that looked like one.

A state diagram answers "what modes can this object be in, and which events move it?" It is the right picture when a boolean has already turned into three booleans. A mindmap answers "what topics are inside this topic?" It has no arrows. An architecture sketch answers "what sits inside this boundary?" It is not a flowchart, and it is not the cloud console.

You don't need to learn them all before you write one. Pick the question in the room. Open that type. The index on the diagrams page is there so the other types remain findable, not so every doc includes every type. A doc with six diagrams of the same feature usually has two that contradict each other. I would rather one accurate flowchart than a set.

Templates are starter claims, not answers. A template that doesn't match your refund rule is worse than a blank file, because the filled-in boxes feel official. Replace the labels before you commit. Delete blocks that describe a step you don't have.

One refund, three artifacts

The same feature wants different diagrams when the questions differ. Here is a refund policy as a flowchart. The claim is about amounts and who approves. Actors are absent on purpose.

mermaid
flowchart TD
  ask[Refund requested] --> gate{Over 50?}
  gate -->|No| auto[Auto approve]
  gate -->|Yes| mgr[Manager review]
  mgr -->|Approved| pay[Send refund]
  mgr -->|Rejected| why[Send the reason]
  auto --> pay
Open in the live editor

Under fifty, we auto approve and send the refund. At fifty or above, a manager approves or rejects. Rejection sends a reason and does not send the refund. There is no arrow from why to pay. That missing arrow is a claim. If finance wants a partial refund on rejection, the chart is wrong and should grow a node. Don't leave the missing arrow as an exercise for the reader.

The sequence answers a different question: who sends the message. The policy is the same. The picture should not invent a second policy.

mermaid
sequenceDiagram
  participant User as User
  participant Shop as Shop
  participant Mgr as Manager
  User->>Shop: Request refund
  alt under 50
    Shop-->>User: Approved
  else 50 or more
    Shop->>Mgr: Review
    alt manager approves
      Mgr-->>Shop: Yes
      Shop-->>User: Refund sent
    else manager rejects
      Mgr-->>Shop: No
      Shop-->>User: Reason
    end
  end
Open in the live editor

If this sequence showed the manager on the under-fifty path, it would contradict the flowchart. I check that on purpose when I keep both. Two diagrams are a feature when they answer two questions. They are a bug when they disagree. The disagreement is often an else someone added in only one file. Read both before the meeting, not during it.

The state diagram answers a third question: what is the refund, as an object, allowed to be. It doesn't show the fifty-dollar rule. That rule is an event that fires a transition, and the amount can live in the transition label or in the flowchart. Stuffing the price table into the state diagram makes a mess of both.

mermaid
stateDiagram-v2
  [*] --> Draft
  Draft --> Review: Submit
  Review --> Draft: Changes requested
  Review --> Sent: Approve
  Review --> Closed: Reject
  Sent --> Closed: Paid
Open in the live editor

Draft, review, sent, closed. You can return to draft from review. You cannot jump from draft to sent. That last constraint is the one product argues about, and it's easier to see as a missing arrow than as a sentence in a ticket. If a bug lets a draft pay out, the diagram is the spec you compare the bug to. If the diagram has the arrow and the code doesn't, the diagram is the bug. Either way you have something to point at.

I didn't draw a fourth picture for the database row. The state names might be a column on a refund table, not their own entities. If someone asks where status lives, that's an ER question, and it gets an ER diagram. It does not get squeezed into stateDiagram-v2 as a note. Different artifact.

When writing one is worth the time

Write a diagram when the claim has a branch, more than one actor, or a constraint someone will forget. Write it when the claim will be reviewed in a pull request. Write it when you expect the claim to change, and you want the change to be a diff instead of a new slide. Write it when a new person asks the same question twice. The second ask is the spec volunteering.

The diagram earns its keep when a reviewer can say "this arrow is wrong" and point at a line. Prose makes that harder. "We usually review large refunds" is not a line number. gate -->|Yes| mgr is. I want the argument to happen on the line.

Write it in the same change as the code when you can. A diagram in a follow-up PR arrives after the review that needed it. A diagram with no code, for a service that already shipped, is still useful if you label it as the behavior you think you have and then check. I have found dead flags this way. The diagram had a branch the code never took. We deleted the branch from both.

Don't write it to decorate a README that nobody argues with. A three-box flowchart of "request comes in, we do the thing, we respond" adds a picture and no claim. The middle box is doing all the hiding. If you can't split the middle box, you don't understand the feature well enough to draw it, or the feature is genuinely one step. One step can be a sentence.

The draw walkthrough is the beginner path for that first real flowchart, built up from two boxes without a design detour. How to make a diagram is the wider pass across types. I send people to the draw page when they are stuck staring at a blank editor, and to the types index when they have a flowchart that keeps growing actors and messages. Growing actors is the hint to switch kinds, not to shrink the font.

An AI diagram generator will draft a legal file from a sentence. The draft is a pile of claims you didn't quite make. Read every arrow. Delete the ones that describe a service you hope to have. I use the draft when I'm blocked on syntax. I don't use it as the review. The review is the reading.

When a whiteboard is still better

A whiteboard is better when the room has not agreed on the claim. Boxes move every thirty seconds. Names aren't stable. Someone is still negotiating whether the manager is in the loop. A Mermaid file at that moment freezes a guess, and the freeze looks like a decision because it's typed. I've frozen the wrong refund threshold this way, and the file outlived the meeting. People trusted it because it was in git.

Stay at the board while the argument is about what should be true. Take a photo if you need memory until tomorrow. Don't transcribe until a sentence survives five minutes without being rewritten. The photo is a snapshot. It is not the artifact. The artifact starts when you type the keyword and you believe the lines.

A whiteboard is also better when the spatial layout carries meaning Mermaid will throw away. A floor plan, a seating chart, a sketch of a machine with parts in physical places. The layout engine will place nodes to reduce crossings, not to match a room. If the position of a box is the claim, this is the wrong tool. I tried to draw a warehouse aisle as a flowchart. The aisle got rearranged into a tidy column. The tidy column was a lie about the building.

It's better in a workshop where half the room will not open a repo. Forcing a projector and a live editor on that room can work, and it can also kill the conversation while someone fixes a missing quote. Draw on the board. Assign one person to transcribe after the decisions, not during the noise. The transcript is the diagram. The board is the thinking. I don't photograph the board and call it done, because the photo doesn't get the next edit. Someone has to type.

It's worse than people admit once the meeting ends. Whiteboards get wiped. The photo loses the arrow that was half erased. The person who drew it remembers a version that isn't the photo. A week later you have folklore. If the claim still matters next week, type it before you leave, while the disagreement is fresh enough to write down accurately. Waiting for a clean version is how the folklore wins.

What the picture is not

It is not the documentation for the whole service. A diagram that tries to be the service has forty nodes and no claim a reviewer can reject. Split by question. Refund policy in one file. Login sequence in another. Schema in a third. Link them. A single "architecture" flowchart that includes the schema, the on-call rotation, and the refund rule is a poster. Posters don't review.

It is not automatically current. Nothing rerenders the truth from your codebase unless you built that, and most teams have not. The file updates when a person updates it. Put it in the pull request template in one line: "if behavior changed, the diagram changed." I have seen that line ignored. It still helps the reviewer who remembers to look. Pair the diagram with the test that locks the same claim if the claim is important enough to break prod. The test doesn't replace the picture. The picture is for the human who won't read the test.

It is not a screenshot of a vendor console, and it shouldn't pretend to be. Generic boxes with honest labels beat a fake icon set. The moment you need the official cloud icons, you are in a different tool, and you should say so. A Mermaid file can still describe the request path among those services without dressing up as the console.

It is not a substitute for the prose around it. The fifty-dollar rule needs a sentence about currency and tax. The diagram needs the branch. Readers who only see the PNG lose the sentence. Keep the sentence in the Markdown above the fence. The syntax post will tell you how the fence is spelled. The docs overview is the map of where those rules live. Neither one decides whether your threshold is fifty.

It is not a drawing you protect from edits because the layout finally looks nice. Layout is computed. The next node will move things. If a tidy layout is load-bearing, you will stop adding the node that makes the claim true. I've done that to preserve a screenshot in a slide deck. The slide stayed tidy. The feature grew a branch the slide didn't have. Ugly and current would have been the better slide.

How a diagram rots

It rots when the code changes and the file doesn't. The fix is social as much as technical. The person who changes the branch changes the diagram in the same PR. Reviewers treat a behavior change without a diagram change as a question: "is the picture wrong, or is there no picture?" Both answers are acceptable. Silence isn't.

It rots when labels include numbers that come from production. An accuracy, a latency, a queue depth. Those belong in a dashboard. Typed into a node, they become fan fiction within a week. I don't put a metric in a diagram unless the metric is a threshold the code actually branches on, like the fifty dollars. Even then, the number in the label must match the constant, and the PR that changes the constant changes the label.

It rots when two copies exist. The wiki PNG, the slide, the fence in the README, the .mmd file someone exported from. Pick the source. Generate the others if a consumer demands them, and assume the generated ones are stale until regenerated. I write the source path in the slide notes. Future me has needed that path.

It rots when the diagram accumulates defensive branches for bugs you have since fixed. A node called "workaround for the 2019 duplicate charge" is a scar. Delete it when the workaround leaves the code. Leaving it "for history" teaches new people to implement the workaround. History belongs in the commit log, which already has the old file.

It rots when names drift. The service got renamed in the repo and not in the label. Grep for the old name. I grep the docs directory when I rename a service, and I still miss the diagram about a third of the time, because the label was a friendly short form. Prefer the name the code uses. Friendliness can live in the prose.

Put it where someone will read it

The README is right for a claim a new contributor needs on day one. A design doc is right for a claim that's still under discussion but stable enough to type. A folder like docs/diagrams/ is right when many pages need the same picture. A slide is wrong as the only copy. A ticket description is wrong as the only copy, because the ticket closes and the claim remains.

Link the diagram from the place the question gets asked. If people ask in the service README, the fence belongs there, not in a private note. If the fence is long, the README can link a doc. A link to a missing file is a special kind of rot. Check it. I have a habit of linking the editor with a draft and forgetting to commit the file. The link works on my machine in the sense that I know what I meant. Nobody else does.

Keep the first line of the diagram easy to find. Keyword, then claims, then stop. A preamble of styling, theme variables, and class definitions before the first node makes the claim start halfway down the file. Default theme. Add color only when two node types are genuinely ambiguous, and even then try renaming first. The picture's job is to make the false claim obvious. Styling rarely helps that, and it often makes the next edit feel expensive.

When you want the picture to follow the keystrokes, paste the file into a live preview and read the claims while they move. It's free and it doesn't require an account. Bring the text back to the repo when the claims are ones you believe. A browser tab is not the system of record. The file in git is. A diagram that exists only in a tab is a whiteboard with extra steps. It will get wiped, just by a closed laptop.

If you're deciding whether to draw at all, use the test from the top. Do you have a claim with a branch, a caller, or a constraint someone will forget? If yes, pick the kind that matches the question and write the smallest file that states it. If the room is still tearing the claim apart, go back to the whiteboard and type it later. The diagram is the artifact you are willing to keep. It is not the argument itself. The argument can be messy. The file should be a set of sentences you can stand next to next month, when the meeting is over and the only thing left is the text. Open the editor when you're ready to type those sentences and watch the picture catch up.

Frequently asked questions

Is a Mermaid diagram the same as Mermaid.js?

The diagram is the text and the picture. The library is what draws it. The 'what is Mermaid' guide covers the library. This page stays with the diagram.

When should I not write one?

Posters, one-off workshops, and anything where the layout is the product. Also when you do not yet have a claim. A diagram of a vibe goes stale immediately.

How many diagram types are there?

More than a design doc needs. Start with flowchart, sequence, class, ER, and state. The diagram index lists the rest.