Skip to content

Documentation as Code

Every documentation practice fails the same way: the documents drift from the system and nobody notices until someone is misled. The previous section established that a wrong description is worse than none, which makes drift the central problem rather than an annoyance.

Documentation as Code is the structural answer. Not a tooling preference — a change to where the document lives, which changes who sees it change.

Keep the architecture documentation as text files in the repository, beside the code they describe. Three consequences follow, and they are the whole argument:

It appears in review. A change that moves a boundary and a change to the document describing that boundary arrive in the same pull request. The reviewer sees both, and the absence of the second becomes visible. Nothing else achieves this: a wiki page cannot appear in a code review.

It is versioned with the system. You can ask what the architecture was believed to be at the point of a release, which is a question that comes up in incidents and is unanswerable when the documentation lives in a page that has only a current state.

Drift becomes a diff. The question “is this still true?” becomes “has the code under this document changed since the document did?” — mechanically checkable rather than a matter of someone remembering.

Compare the alternative honestly. A wiki is easier to write in, easier to format, and easier for non-engineers to reach. It is also disconnected from the thing it describes, which means drift is invisible until it has already cost somebody. The trade is accessibility against staleness, and staleness is the failure that actually occurs.

graph TD
  A["Boundary moves<br/>in the code"] --> B{"Where does the<br/>document live?"}
  B -->|"In the repository"| C["<b>Same review</b><br/>missing update<br/>is visible"]
  B -->|"Elsewhere"| D["<b>Nobody sees it</b><br/>drift is invisible<br/>until it misleads"]

  classDef ev fill:#5B8FB9,stroke:#4A7A9E,stroke-width:2px,color:#ffffff
  classDef q fill:#E8A33D,stroke:#C4832A,stroke-width:2px,color:#ffffff
  classDef good fill:#7D9A4E,stroke:#5F7A38,stroke-width:2px,color:#ffffff
  classDef bad fill:#D9695B,stroke:#B4483A,stroke-width:2px,color:#ffffff
  class A ev
  class B q
  class C good
  class D bad

One question decides whether drift is caught or accumulates. Everything else about documentation tooling is secondary to it.

The same argument applied to pictures, and it matters more because diagrams rot faster and lie more convincingly.

A diagram authored as text can be diffed, reviewed, regenerated and kept in the same commit as the change it describes. A diagram pasted in as an image can only be replaced wholesale, which means in practice it is not replaced. An exported image also hides what changed: a reviewer sees that the picture is different and cannot see how.

The cost is real. Text-authored diagrams are less expressive, the layout is largely out of your hands, and some diagrams are genuinely better drawn by hand. The judgement is by lifespan, which is the whole module’s organising property: a diagram that must stay current should be text; a one-off diagram for a specific conversation can be drawn however is fastest. Module 8’s single-diagram pitch artifact is a drawn diagram, and that is correct — it has a lifespan of one meeting.

Simon Brown’s tooling, from the same author as the C4 model, and worth naming specifically because it holds both halves: C4 diagrams and decision records, as text, alongside the code. Diagrams are defined once as a model and rendered at several levels, so the context view and the container view cannot contradict each other — a failure mode that is otherwise routine when the two are separately maintained pictures.

The reason to care about that pairing rather than the tool: the two artifacts this module cares about most are the description and the explanations, and keeping them in one place with one review path is what makes the pointers between them stay valid.

Non-engineers lose easy access. Real, and it is the main objection. The mitigation is publishing the rendered output somewhere readable, which is a build step rather than a second source of truth.

Writing in a repository is less pleasant than writing in a document tool, and this suppresses contribution from people who would otherwise help.

Review adds latency. Usually worth it; occasionally it means a correction sits for two days.

None of these is fatal, and all are smaller than the cost of a confidently wrong description of the system.

This is most of the documentation structure artifact: where each document lives, what triggers its revision, and what gets published outward for the non-engineering readers.


→ Documents in the repository have a second reader now, and it is not a person. — Documentation as Context