Docs & Code Guide

Mermaid diagram drift: diagrams as code still need a human to type the change

By the engineer who builds Datadef, from client work on data platforms · Reviewed August 21, 2026

Moving diagrams into the repository as mermaid was a real improvement. The file diffs, it reviews, it renders natively in GitHub and GitLab markdown, and there is no binary blob and no licence for a drawing tool. What it did not do is make the diagram a function of the code. A mermaid block is still a hand-written assertion about the system, and a hand-written assertion drifts the moment somebody ships a change and does not think about the picture.

7 min readFor teams who moved to diagrams as code and still have wrong diagrams

See it as a diagram

Everything below, as a diagram you can edit. Describe yours and see it in seconds.

127/20003 credits left
Try:

No account needed · Editable canvas, not a picture

What diagrams as code actually fixed

Version control. The diagram now lives on a branch, moves with a tag, and can be reverted. That was the biggest practical problem with a drawing tool export and it is genuinely solved.

Reviewability. A change to the graph appears in the pull request as text a reviewer can read. Compared to a binary image where the diff is unreadable, this is a large win, and it is why teams who adopt mermaid do see fewer wrong diagrams for a while.

Proximity. The diagram is in the same repository as the thing it describes, so the effort of updating it drops from open another tool to edit a file you already have open. Lower effort means more updates, which is real.

None of that is accuracy. Being reviewable makes drift visible to a reviewer who happens to notice. It does not make drift impossible, and it does not tell anyone that a diagram was supposed to change.

The three shapes mermaid drift takes

Silent omission. Someone adds a call from the orders service to a new pricing service. Nothing fails, no test is red, no reviewer thinks about the README, and the graph now describes a system with one fewer edge than reality. This is the most common and the most damaging, because the diagram looks complete.

Rename skew. A module is renamed in code, every import updated by the tooling, and the mermaid node keeps the old label because no refactoring tool touches a markdown fence. Six months later two names are in circulation and new joiners assume they are two different things.

Layout collapse. Mermaid lays out automatically, and automatic layout degrades as the node count rises. The tangle is not the real problem; the real problem is that maintaining something unreadable feels pointless, so the file keeps growing for a few months out of habit and then freezes. Completeness is what causes this, and it is a trap for generated diagrams too: an early completeness pass of Datadef Terraform pipeline drew 62 resources from a 123-resource repository and produced a column that was correct, complete and unreadable.

A fourth, less discussed: the copy in Confluence. Mermaid renders in GitHub, so the wiki gets a pasted screenshot, and the screenshot is a separate artefact with a separate decay rate. See embed diagrams in markdown for the version of this that does not fork.

<!-- README.md, committed 2025-11, still there today -->
graph TD
  api --> orders
  orders --> ordersdb
  orders --> events

<!-- Since then, in code and not in the graph:
     orders now calls pricing before writing
     ordersdb was split into orders and inventory
     events gained a second consumer
     nothing failed, so nobody noticed -->

Generated for inventory, authored for intent

The useful split is not mermaid versus a drawing tool, it is inventory versus intent. Inventory diagrams answer what exists and how it is wired, they change every sprint, and they should be generated. Intent diagrams answer what we are planning, how this one flow works, or what the boundary should be, they change when thinking changes, and they should be authored by a person.

Keep mermaid for intent. A sequence diagram for a single feature, a proposal attached to an ADR, a state machine that genuinely does not change: all of these are good uses of a hand-written text diagram, and none of them decay in the way an inventory diagram does. Being wrong is even acceptable for a proposal, because it is dated and superseded.

Generate the inventory, and make the generator curate. Connect the repository read only through repository sync, choose a branch or a tag, and the diagram is redrawn daily. For Terraform repositories every .tf file is parsed with no state and no cloud credentials, modules become zones, and the curation is deterministic rather than left to the model: a resource classified as glue, meaning a role assignment, a grant, a random password or anything from the random, null, local, time, tls, archive or template providers, is never a box and is counted in a summary instead. Repeated minor types inside a module collapse into one node carrying the count and the member names, and a module is allowed eight drawn nodes before its tail collapses into a named supporting-resources node, sixteen when that one module is effectively the whole repository. Nothing is lost: the counts ride on the canvas and the full inventory is the Module reference table in the generated architecture doc.

Then the README block becomes one line. Instead of eighty lines of graph declaration that a human owns, the markdown holds a live embed URL rendering the current canvas, readable without an account, and the maintenance burden goes to zero.

Completeness is the tell

A graph that grows one node per new component is on its way to being unreadable and therefore unmaintained. That is the point to generate the inventory, let the generator roll up the repetition, and keep mermaid for the small intentional diagrams.

If you are staying with mermaid

Put the diagram file next to the code it describes rather than all diagrams in one docs directory. A reviewer touching internal/orders is far more likely to notice internal/orders/README.md than a file three levels away.

Add a CODEOWNERS entry so the team that owns the code is requested on changes to the diagram, and so a change to the code without a change to the diagram is at least visible to the same people.

Cap the scope of each diagram deliberately. Three diagrams of ten nodes each stay maintained far longer than one diagram of thirty, because each one has an obvious owner and stays legible. See the limits of docs as code for diagrams.

FAQ

Do mermaid diagrams solve documentation drift?

Only partly. They fix versioning, review and proximity, so the diagram diffs in the pull request and lives beside the code. They do not make the diagram a function of the code, so a change that nobody thinks about still leaves the graph describing a system that no longer exists.

Where do mermaid diagrams usually go wrong?

Three ways. A new dependency is added in code and no edge is added to the graph, and nothing fails. A module is renamed and the node label keeps the old name because refactoring tools do not touch markdown fences. And the graph grows past the point where automatic layout stays readable, after which people stop maintaining it.

How many nodes should an architecture diagram carry?

Fewer than the system contains. Drawing everything is what makes a diagram unreadable and therefore unmaintained. An early completeness pass of Datadef Terraform pipeline drew 62 resources from a 123-resource repository and produced a phone book. Either scope each hand-written diagram narrowly, or generate the large one and let the generator roll repetition into counted nodes.

Should some diagrams still be written by hand?

Yes. Diagrams that express intent rather than inventory: a proposal attached to a decision record, a sequence diagram for one feature, a state machine. Those change when thinking changes rather than when code changes, and a text format in the repository suits them well.

How do you replace a hand-written graph in a README?

Generate the inventory diagram from the repository, then replace the code fence with a single markdown image line pointing at the live diagram URL. The README then renders whatever the canvas currently holds, and there is no graph declaration for anyone to keep updating.

What happens to the wiki copy of a mermaid diagram?

It usually becomes a pasted screenshot, because mermaid renders in the repository host but not always in the wiki. That screenshot is a separate artefact with its own decay, which is why referencing one diagram URL from both places is better than exporting to each.