Skip to main content

Conceptadvanced

Living Documentation

Overview

All hand-written documentation goes stale. The problem is not discipline — it is that the information exists in two places and nothing forces the two to agree.

Living documentation attacks the cause: derive the documentation from the artifact that is already true, so that diverging is impossible, and not merely undesirable.

And this topic's central decision is not which tool to use. It is what can be derived and what cannot — because most architectural value lies precisely in what the machine doesn't know.

Problem

The cycle is familiar:

someone writes the documentation
the system changes
the documentation doesn't
someone trusts it and gets it wrong
confidence drops
nobody consults it
nobody updates it

And the usual remedy — process, reminders, mandatory review — fights the symptom. It depends on someone doing, every single time, work that gives no immediate return to whoever does it.

See documentation principles, where documentation half-life is the corresponding concept.

Core Concepts

What can be derived

deployment diagram from the infrastructure code
container diagram from a service manifest
component structure from the code
API contracts from the specification or the code
data schema from the database
dependencies between services from distributed tracing
system inventory from the registry
who-calls-whom matrix from the service mesh or the logs

The pattern is clear: structure is derivable. What exists, how it connects, what runs where — all of it is declared somewhere executable.

See distributed tracing for the last category, which is the most reliable of all: it shows what happens, not what was declared.

What cannot be derived

why the decision was made
which alternatives were discarded
which constraint shaped the choice
what is intended to change
what is known to be wrong
what the boundary means in business terms
who the system exists for

None of that is in the code. It is intent, and intent only exists written down.

That division is the most useful thing in this topic: derive the structure, write the intent, and don't try to invert it. See architecture decisions.

Diagrams as code

Describing diagrams in text and rendering them is the practical middle ground:

versioned alongside the code
enters code review
diffs are legible
the text is useful even without rendering

It is not derivation — the text is still written by hand, and it can still diverge. The gain is in the process: a text diagram in the repository is reviewed alongside the change that affects it, and the trigger is natural.

The trade-off is layout: automatic renderers produce acceptable arrangements and rarely optimal ones. For sequence diagrams that hardly matters; for large structural ones, it does. See diagram quality.

Verification instead of generation

A cheaper and frequently better alternative: keep the documentation written and automatically verify that it agrees with reality.

do the containers named in the diagram exist in the registry?
do the deployed services appear in the diagram?
do the documented endpoints respond?
does the declared owner exist?
do the links resolve?

That preserves the curation — layout, emphasis, grouping — and eliminates silent divergence. When the verification fails, a person decides what to fix: the document or the system.

And sometimes the answer is the system. A check that points at a deployed and undocumented service may have found something that shouldn't be running.

Tests as documentation

Acceptance tests written in domain language describe behavior and cannot diverge, because they fail when they do.

what the system does legible in the test
under what conditions same
what happens when it fails same

The limitation: tests describe behavior, not structure or intent. They cover a real slice and do not replace the rest. See contract testing.

The up-front cost is real

Derivation is not free:

building the extraction weeks
maintaining the tool continuous
handling irregular cases constant
sometimes ugly output always

The calculation: derivation pays off where the information changes frequently and is consulted frequently. Where either is low, writing by hand and verifying is cheaper.

That is the case with the context diagram — it barely changes, and deriving it would mean building machinery for a problem that doesn't exist. See context diagrams.

Mental Model

Derive the structure, write the intent, verify the rest. What the machine knows, the machine documents.

When to Use

  • For deployment diagrams, where the topology is already declared.
  • For API contracts and data schemas.
  • For inventories and dependencies between services.
  • For the component level, the one with the shortest half-life.
  • As verification, in any written documentation.

When Not to Use

For rationale and decisions — not derivable.

Where the information changes little — the cost doesn't pay off.

When layout matters a lot and the generated version is illegible.

With nobody responsible for the tool — the tool becomes the new debt.

As a substitute for writing — the result is complete and meaningless documentation.

The last deserves emphasis: an organization that generates everything and writes nothing has correct diagrams and no explanation of why the system is the way it is.

Alternatives

  • Writing with a trigger — update when the corresponding event occurs. See documentation standards.
  • Automated verification — cheaper than generation, preserves curation.
  • Diagrams as code — the middle ground, a process gain.
  • Accepting aging with a visible date — legitimate for what changes little.

Trade-offs

GeneratedWritten
Cannot divergeCan
Shows what existsShows the intent
Automatic layoutCurated
High up-front costContinuous cost
GenerationVerification
Eliminates divergenceDetects it
Loses curationPreserves it
Expensive to buildCheap
Always currentCurrent or red

Failure Modes

Generate everything, write nothing. Correct structure, no intent.

A tool with no owner. It breaks and nobody notices.

An illegible generated diagram. No grouping, with dozens of nodes.

Deriving what doesn't change. Machinery with no return.

Verification that always fails. It becomes noise and is ignored.

The wrong derivation source. Deriving from what was declared, not from what runs.

Common Mistakes

Trying to derive rationale. The code shows what is, never why it was chosen. Automation does not replace recording the decision.

Not distinguishing structure from intent. Structure is derived and verified; intent is written by hand. Treating both the same leads to automating what can't be and hand-writing what ages.

Choosing the tool before deciding what to derive. The tool generates what it knows how to generate, and the result is abundant documentation nobody asked for.

Not measuring whether the output is read. Generated documentation has a maintenance cost like any other. If nobody opens it, the right move is to turn the generation off.

Ignoring verification as the cheaper option. For many properties, a test that fails when the rule is violated is worth more than a document that describes it — and it never goes stale.

Real-World Example

A company with 180 services maintained an architecture portal with hand-drawn diagrams. The accuracy rate measured on a sample was 34%.

The first attempt was to generate everything. An extractor read the orchestrator, the service mesh and the repositories, and produced diagrams automatically.

The technical result worked. The practical result was bad:

diagrams with 180 nodes and 900 edges
no grouping by domain
no distinction between a critical and an occasional call
no indication of purpose

The diagrams were correct and illegible. Use of the portal dropped even further.

The second attempt separated by the nature of the information:

Derived — service inventory, real dependencies from tracing, deployment topology, API contracts, data schemas. All continuously updated, available as a query and not as a giant diagram.

Written and verified — context and container diagrams per domain, hand-drawn, with curated grouping and emphasis. A daily check compares the drawn containers with the deployed services and raises an alert to the owner when they diverge.

Written, with no verification possible — rationale, ADRs, risks, evolution intent.

Grouping by domain applied to the derived data: instead of one 180-node diagram, a query answering "what does this domain depend on" with five to twelve nodes.

The numbers, a year later:

accuracy rate of the written diagrams 34% → 89%
divergences detected per month an average of 11, fixed within days
undocumented services found 7 (three of which shouldn't exist)
portal usage 2.4× the previous level

The seven services found by the verification were an unforeseen result: three were leftover experiments still running, consuming resources and holding access to production data.

Full generation failed not because it was technically wrong, but because it ignored that curation is content. Grouping by domain and emphasizing certain relationships is architectural information — and it is exactly what automated extraction has no way of knowing.

Practical Exercise

List your system's documentation artifacts in two columns: what could be derived from something that already exists, and what only exists because someone wrote it.

The second column is what deserves the human effort. The first is a candidate for automation or verification.

Interview Questions

  • What kind of information can never be derived, and why?
  • Why is verification usually a better deal than generation?
  • How can generated documentation be 100% correct and useless?

Further Reading

  • Martraire, Cyrille. Living Documentation. Addison-Wesley, 2019.
  • Adzic, Gojko. Specification by Example. Manning, 2011.
  • Brown, Simon. Software Architecture for Developers. Leanpub, 2015.
Finished reading this document?Your progress is saved in this browser only.