Diagrams as Code — Junior Level¶
Category: Documentation — write architecture and flow diagrams in plain-text markup, commit them next to the code, and render them automatically — instead of pasting binary screenshots that rot.
Table of Contents¶
- Introduction
- Prerequisites
- Glossary
- The Problem: The Diagram That Rots
- The Idea: Diagrams as Code
- Why This Matters
- Your First Diagram: Mermaid
- The Common Diagram Types
- The Same Idea in PlantUML
- Graphviz / DOT
- Where Diagrams Live
- Which Diagram Answers Which Question
- Good Diagram Habits
- Best Practices
- Common Mistakes
- Tricky Points
- Test Yourself
- Cheat Sheet
- Summary
- Further Reading
- Related Topics
- Diagrams
Introduction¶
Focus: What is it? and How to use it?
Diagrams as code means you write a diagram as a few lines of plain text — a small markup language — and a tool renders it into a picture automatically. The text lives in your repository, next to the code it describes, and is reviewed, versioned, and regenerated exactly like source code.
A diagram as code is a diagram defined in committed, human-readable text markup and rendered automatically — never a hand-placed binary image exported from a drawing tool.
Here is the entire idea in one block. This is real Mermaid source; on GitHub, GitLab, or an MkDocs site it renders as an actual picture:
Five lines of text. No mouse, no dragging boxes, no exporting a PNG. You committed the recipe for the picture, and the platform draws it for you. Change a line, and the picture changes — automatically, in the next render.
Prerequisites¶
- Required: comfort with Markdown and committing files to Git — diagrams-as-code lives in Markdown files in a repo.
- Required: you have opened a pull request and had code reviewed — the payoff is diffable, reviewable diagrams.
- Helpful: a rough mental picture of a typical web system (client, server/API, database) so the examples make sense.
- Helpful: exposure to READMEs and code comments/docstrings — diagrams usually live inside these.
Glossary¶
| Term | Definition |
|---|---|
| Diagram as code | A diagram written as plain-text markup, committed to the repo, and rendered automatically. |
| Mermaid | A text-to-diagram syntax that renders natively in GitHub, GitLab, and many doc tools — the easiest entry point. |
| PlantUML | An older, more complete text-to-diagram tool covering all UML diagram types; renders via a server or local jar. |
| Graphviz / DOT | A graph-layout engine; you describe nodes and edges in the DOT language and it auto-arranges them. |
| Render | Turn the text markup into an actual image (SVG/PNG) — done by the platform or in CI. |
| Doc rot | Documentation that has silently drifted out of sync with reality; a stale screenshot is the classic example. |
| Diff | The line-by-line change view in Git; text diagrams produce readable diffs, binary images do not. |
| Single source of truth | One authoritative place a fact lives; for a diagram, the committed markup — not a copy in someone's drawing tool. |
The Problem: The Diagram That Rots¶
Picture the usual lifecycle of a diagram drawn the old way:
- An engineer opens Lucidchart, draw.io, or Visio and drags boxes around for an hour.
- They export a
architecture.pngand paste it into the wiki or README. - The system changes — a new service is added, a queue is introduced, a database is split.
- Nobody updates the picture. Updating it means finding the original file, reopening the GUI tool, re-arranging, re-exporting, re-uploading.
- Six months later the diagram confidently shows an architecture that no longer exists. A new hire trusts it and wastes a day.
This is doc rot, and the screenshot-of-a-whiteboard is its purest form — out of date the instant the marker stops moving. (Fighting rot is a whole topic on its own: Keeping Docs Alive.)
The root causes are all about friction and invisibility:
| Problem with binary-image diagrams | Consequence |
|---|---|
| Lives outside the repo (or as an opaque blob inside it) | Drifts from the code; nobody is reminded to update it |
| Editing needs a GUI tool and the original source file | High friction → people don't bother |
A .png shows as "Binary file changed" in a PR | Can't be reviewed; no one catches a wrong arrow |
| Only the original author can change it | Knowledge is trapped; diagram dies when they leave |
The Idea: Diagrams as Code¶
Diagrams as code flips every one of those problems:
| Binary image (old way) | Diagram as code |
|---|---|
| Drag-and-drop in a GUI tool | Write a few lines of text |
Exported .png / .svg blob | Source markup committed to the repo |
| Lives in a wiki / Google Drive | Lives next to the code it describes |
| "Binary file changed" in the diff | A readable line-by-line diff in the PR |
| Updated manually, rarely | Regenerated automatically by the platform / CI |
| Edited only by its author | Edited by anyone who can write text |
The mental shift is exactly the same one the industry made for infrastructure (Infrastructure as Code) and configuration: stop clicking, start committing. When the picture is generated from committed text, it can be reviewed, versioned, branched, and diffed — and it can never quietly drift, because the text is the diagram and the text is in the repo with everything else.
Why This Matters¶
- Version-controlled. Every change to the diagram is a commit with an author, a date, and a message. You can
git blamea box and find out who added it and why. - Diff-able and reviewable. A teammate sees
API --> Cacheappear in the PR diff and can comment "shouldn't that arrow go the other way?" You cannot review a screenshot. - Lives next to the code. The diagram is in the same repo, often the same folder. When you touch the code, the diagram is right there, harder to forget.
- No drift between a stale PNG and reality. Because the source is text in the repo, an out-of-date diagram shows up as out-of-date code — caught in review like any other staleness.
- Regenerated in CI. A pipeline can re-render every diagram on each commit, so the published picture always matches the latest committed markup.
- Accessible to every engineer. You don't need design skills or a license to a drawing app. If you can type, you can produce a clean diagram — and update someone else's.
The one-line argument: a diagram-as-code is a diagram that participates in your normal engineering workflow — commit, review, merge, CI — instead of living outside it where it rots.
Your First Diagram: Mermaid¶
Mermaid is the place to start, for one decisive reason: GitHub and GitLab render it natively inside Markdown. You write a fenced code block tagged ```mermaid, push it, and the picture appears in the rendered Markdown — no tooling, no build step.
A flowchart (process / logic):
A sequence diagram (who talks to whom, in what order):
Notice what you did: you described intent ("user posts an order, the API inserts it, the DB returns an id") and Mermaid handled all the layout, arrows, and spacing. You never positioned a single box.
The basic flowchart vocabulary you need on day one:
flowchart TD direction: TD=top-down, LR=left-right, BT, RL
A --> B solid arrow from A to B
A -- text --> B arrow with a label
A([Rounded]) a "start/end" shape
A{Decision?} a diamond (branch)
A[Box] a plain rectangle (step)
The Common Diagram Types¶
Mermaid (and the other tools) support far more than flowcharts. The most useful for an engineer:
An ER (entity-relationship) diagram — the shape of your data:
A class diagram — structure of objects/types:
A state diagram — the lifecycle of one thing:
You don't need to memorize the syntax — you look it up the first few times. What matters is recognizing that each diagram type answers a different question, covered below.
The Same Idea in PlantUML¶
Mermaid isn't the only tool. PlantUML is older, supports the full UML standard, and is extremely popular in enterprise and Java circles. It renders via a small server or a local Java jar (and GitHub does not render it natively — you commit the .puml source and render it in CI or via a service like Kroki).
Here is the same sequence as the Mermaid example above, in PlantUML:
@startuml
actor User
participant API
database Database
User -> API : POST /orders
API -> Database : INSERT order
Database --> API : order id
API --> User : 201 Created
@enduml
Same idea, different syntax. PlantUML tends to be more verbose but more capable (it covers component, deployment, and other UML diagrams Mermaid handles less fully). For a junior the takeaway is: these are alternative dialects of the same concept — text in, picture out. Pick the one your platform renders most easily; for most teams on GitHub/GitLab that is Mermaid.
Graphviz / DOT¶
Graphviz is the granddaddy: a pure graph-layout engine with a tiny language called DOT. You declare nodes and edges; Graphviz computes a nice layout. Tons of tools generate DOT under the hood (dependency graphs, profilers, compilers).
digraph services {
rankdir=LR;
web -> api;
api -> db [label="reads/writes"];
api -> cache;
worker -> queue;
queue -> worker;
}
Run dot -Tsvg services.dot -o services.svg and you get a laid-out picture. You'll meet DOT most often as generated output from other tools, but it's worth recognizing.
Where Diagrams Live¶
The whole point is that diagrams live with the code and docs, embedded directly in the Markdown:
- In a README to show the high-level architecture (READMEs & Onboarding).
- In a design doc / RFC to show the proposed design (Design Docs & RFCs).
- In an ADR to illustrate a decision (Architecture Decision Records).
- In a runbook to show an incident flow or system topology (Runbooks & Ops Docs).
- In a docs site built with the docs-as-code toolchain (Docs as Code & Tooling).
Because the diagram is a fenced block inside the Markdown, it travels with the document, renders in the same view, and is reviewed in the same PR.
Which Diagram Answers Which Question¶
The single most useful skill is matching the diagram type to the question it answers. A diagram is a tool for answering one question for one audience.
| You want to show… | Use this diagram | It answers |
|---|---|---|
| How components talk over time / a protocol | Sequence | "In what order do these parts call each other?" |
| Logic, a process, a decision flow | Flowchart | "What are the steps and branches?" |
| The shape of your data | ER diagram | "What entities exist and how are they related?" |
| Object/type structure | Class diagram | "What are the types and their relationships?" |
| The lifecycle of one thing | State diagram | "What states can this be in, and what transitions are legal?" |
| Where software runs (infra) | Deployment diagram | "What runs on which machine/network?" |
| The big picture of a system | Context / Container (C4) | "What is this system, and what are its major parts?" |
Rule of thumb: one diagram, one question, one audience. A diagram trying to show data and runtime and logic at once usually shows none of them clearly.
Good Diagram Habits¶
Even at the junior level, a few habits separate a useful diagram from a confusing one:
- Give it a title. A diagram with no caption forces the reader to guess what they're looking at.
- Be consistent with arrows. Decide what an arrow means (a call? a data flow? a dependency?) and keep it the same throughout one diagram.
- Keep one level of abstraction. Don't mix a high-level "Payments Service" box with a low-level "for-loop" box in the same picture.
- Keep it small. Many small focused diagrams beat one giant "everything" diagram nobody can read.
- Embed it in the doc. A diagram in a folder by itself is half-useful; a diagram inside the README/ADR/runbook that explains it is fully useful.
Best Practices¶
- Default to Mermaid when your platform renders it natively (GitHub/GitLab/MkDocs). Zero setup, instant rendering.
- Commit the source, not just the image. The text markup is the source of truth; a rendered PNG, if you keep one, is a build artifact.
- Put the diagram next to what it describes — inside the README, ADR, design doc, or runbook.
- Pick the right diagram type for the question (use the table above).
- One diagram, one idea. Split a complex picture into several focused ones.
- Treat the diagram like code: it goes through the same PR/review as the change it documents, updated in the same commit.
Common Mistakes¶
- Pasting a screenshot of a drawing tool into the docs — instantly un-reviewable and starts rotting immediately.
- The everything-diagram. One sprawling picture with forty boxes that answers no question clearly.
- Mixing abstraction levels — a cloud-region box next to a single function in the same diagram.
- Inconsistent arrows — some arrows mean "calls", some mean "data flows", some mean "depends on", with no legend.
- Committing only the rendered
.pngand losing the source, so the next person is back to a binary blob. - Letting the diagram drift — changing the code in a PR but not the diagram in the same PR. Diagrams are docs; they rot too.
Tricky Points¶
- GitHub renders Mermaid natively; it does not render PlantUML or DOT natively. For PlantUML/Graphviz you render in CI or via a service like Kroki, then embed the resulting image — or you use a docs tool that supports them. This is the most common surprise for beginners.
- A diagram is documentation, so it can rot. "Diagrams as code" reduces rot dramatically (it's diffable and lives with the code) but does not eliminate it — you still must update the markup when reality changes.
- Auto-layout is convenient but not always pretty. The tool chooses the layout; you trade pixel-perfect control for zero maintenance. Usually a great trade, occasionally annoying.
- The fenced block must be tagged correctly (
```mermaid), or the platform shows raw text instead of a picture.
Test Yourself¶
- In one sentence, what is a "diagram as code"?
- Why does a screenshot pasted into a wiki "rot," and how does diagrams-as-code fix that?
- Name the two biggest advantages of text-based diagrams over exported images.
- Which tool renders natively in GitHub Markdown, and which one usually needs CI or a render service?
- Match each to its question: sequence, ER, state, flowchart.
- What does "one diagram, one question, one audience" mean in practice?
Answers
1. A diagram defined as committed plain-text markup that a tool renders into a picture automatically, instead of a hand-drawn binary image. 2. A screenshot lives outside the code, can't be diffed/reviewed, and is high-friction to update, so nobody does — it drifts from reality. Diagrams-as-code put the source text in the repo, diffable and reviewed in the same PR as the code, so staleness is caught. 3. (Any two) version-controlled with readable diffs; reviewable in PRs; lives next to the code; regenerated in CI; editable by anyone who can type. 4. **Mermaid** renders natively in GitHub/GitLab Markdown; **PlantUML** (and Graphviz/DOT) typically need CI rendering or a service like Kroki. 5. Sequence → order of interactions over time; ER → shape of the data/relationships; state → lifecycle/legal transitions of one thing; flowchart → steps and decision branches of a process. 6. Each diagram should answer a single question for a single reader; if it's trying to show data, runtime, and logic at once, split it into several focused diagrams.Cheat Sheet¶
WHAT diagram written as committed text markup, rendered automatically
WHY versioned · diffable · reviewable · next to code · CI-rendered · no drift
START WITH Mermaid (renders natively on GitHub/GitLab/MkDocs)
ALSO PlantUML (full UML, render via CI/Kroki) · Graphviz/DOT (graph layout)
DIAGRAM → QUESTION
sequence → order of interactions / a protocol
flowchart → steps & decision branches
ER → shape of the data
class → type/object structure
state → lifecycle & legal transitions
deployment → what runs where
C4 context/container → the big-picture architecture
HABITS title it · consistent arrows · one abstraction level ·
small & focused · embed in the doc · update in the SAME PR
Summary¶
- Diagrams as code = write a diagram in plain-text markup, commit it, render it automatically. Stop clicking, start committing.
- It fixes the rotting screenshot: text diagrams are version-controlled, diffable, reviewable in PRs, live next to the code, and can be regenerated in CI.
- Mermaid is the easiest start (native GitHub/GitLab rendering); PlantUML covers full UML; Graphviz/DOT is a graph-layout engine.
- Match the diagram type to the question: sequence, flowchart, ER, class, state, deployment, context/container.
- Good habits: title it, consistent arrows, one abstraction level, keep diagrams small and focused, embed them in the doc, and update them in the same PR as the code.
- Diagrams are documentation — they still rot if you don't maintain them.
Further Reading¶
- Mermaid documentation — syntax for every diagram type, with a live editor.
- PlantUML — the full UML reference and language guide.
- Graphviz / DOT language — the node/edge layout language.
- Kroki — one HTTP service that renders Mermaid, PlantUML, Graphviz, and more.
- The C4 model (Simon Brown) — c4model.com — covered at the Middle level.
Related Topics¶
- Next: Diagrams as Code — Middle
- Diagrams live inside: READMEs, Design Docs & RFCs, ADRs, Runbooks.
- Rendered & versioned by: Docs as Code & Tooling.
- The rot they fight: Keeping Docs Alive.
Diagrams¶
Documentation · Roadmap · Next: Diagrams as Code — Middle
In this topic
- junior
- middle
- senior
- professional