Legacy

How do I document a legacy system nobody understands?

Documentation projects on legacy systems almost never finish. Not because people give up — because nobody can tell how much is left.

Short answer

Do not run a documentation project. Split the work: derive everything that is a fact about the system, and write by hand only the small number of things that are decisions or habits. Deriving is bounded and repeatable; writing is where a person's time is worth spending. The measure of progress is not pages written but open questions closed — a list that visibly shrinks, which is the thing an unbounded documentation effort can never provide.

#Why documentation projects fail here

Four reasons, and none of them is that people are lazy.

  1. Unbounded scope. Nobody can say what "documented" means for a system nobody understands, so there is no state in which the project is finished.
  2. No visible progress. Twelve pages written out of an unknown total is not progress anybody can report, defend or feel.
  3. Written from memory, about a system nobody remembers. The usual method — sit somebody down and have them write what they know — does not work when the answer is that they do not know.
  4. It goes stale while being written. A six-month documentation effort describes a system that changed during those six months, and nothing connects the two.

The common thread: the method assumes a knowledgeable author, and a legacy system is by definition one where none is available.

#The split

Two kinds of knowledge, two methods
Facts about the systemDecisions and habits
ExamplesComponents, dependencies, endpoints, data flows, scheduled workWhy this design, what was tried, what breaks, what to check
Where it livesIn the systemIn people, if anywhere
MethodDeriveAsk, and write down the answer
EffortHours, repeatableMinutes per item, unrepeatable
VolumeMost of itA page or two
Goes stale?Yes — so rebuild itNo. A decision from 2021 is still what happened in 2021

The last row is the one that changes how this feels. Decisions do not decay: "we tried X and it did not work because Y" is permanently true. Facts about the system decay constantly — which is exactly why they should be derived rather than typed.

#Making it bounded

The single change that makes this tractable: stop measuring pages and start measuring open questions.

  1. Derive the picture and let it produce a gap list

    An analysis that reports what it could not establish gives you a finite, prioritised list — eleven questions, four of which matter.

    This is the moment an unbounded worry becomes a bounded task, and it is the whole trick.

  2. Rank the list by consequence

    Not by how interesting the question is. By what it would cost to be wrong about it — money, data, an outage, a regulatory obligation.

  3. Close them one at a time, and record who answered

    Some are answered by reading a specific file. Some by asking a person. Some by looking in a cloud console. Each closed question is a paragraph, with a date and a name.

  4. Re-derive after material change, and compare

    The facts half updates itself. New questions appear where the system moved, which is exactly what you want to be told about.

Progress is now reportable: "we started with thirty-one open questions; there are nine left, and the four high-priority ones are closed." That is a sentence a documentation project can never produce.

#The small amount worth writing

Per subsystem, a page at most. Written as answers rather than as sections, because answers can be checked against a question and sections cannot.

  • What this part is for, in business terms, in two sentences.
  • What we established and how, with the evidence — a file, a console, a person.
  • What we still do not know, and why it has not been closed.
  • What to be careful with, and the specific reason.
  • What we tried that did not work, if anybody remembers.
  • Who to ask, if anybody is left.
A subsystem page that is worth its length Invented example — not a customer
NIGHTLY EXPORT                       reviewed 2026-08-25 · M. Piskunov

For        Sends the previous day's payments to a partner as a CSV.

Established
  Runs at 02:00 from a crontab on the app server, not from the
  repository scheduler.        (evidence: /etc/cron.d/export, server)
  Writes to a path taken from EXPORT_DEST, set in the environment
  and not in the repository.   (evidence: app/Console/Export.php:31)

Not known
  Who receives the file. EXPORT_DEST resolves to an SFTP host
  nobody in the company recognises.                     HIGH
  Whether anybody notices when it fails.                MEDIUM

Careful
  It has no error handling. A failure is silent, and there is no
  alert. Assume it has failed at some point without anybody knowing.

Ask
  Nobody left. The account was created by a contractor in 2022.

Twenty lines. It is more useful than twenty pages of architecture prose, because every line is either evidenced or explicitly marked as not known — and the two open questions are actionable today.

#Where to keep it

  • The derived picture — wherever it is derived, refreshed when the system changes. Not copied into a wiki, where it will drift from its source.
  • The open questions — in one list, visible to everybody, with closed items kept rather than deleted.
  • The written pages — in the repository, next to the code, in plain files. They then move with the code, appear in reviews, and survive a change of wiki.

One rule that matters more than the choice of tool: date and attribute everything. A page about a legacy system is read years later by somebody deciding how much to trust it, and a name and a date are most of what they have to go on.

#What goes wrong

Starting a documentation project.

Instead Derive the facts and work an open-questions list. Bounded, measurable, and it finishes.

Measuring progress in pages.

Instead Measure it in questions closed. Pages written is an input, not an outcome.

Copying the derived picture into a wiki.

Instead Link to it. A copy is a second version that will disagree with the first within a quarter.

Writing what you assume rather than what you established.

Instead Separate the two explicitly, on the page. “Established, with evidence” and “not known” are different sections for a reason.

Undated, unattributed pages.

Instead A name and a date on everything. Without them a future reader cannot weigh anything you wrote.

#What this does not cover

What this does not do

  • User-facing product documentation, which has a different audience and a different method.
  • API documentation for external consumers, which is a published artefact with its own obligations.
  • Compliance documentation, whose form somebody else specifies.
  • Recovering reasoning that nobody remembers. Where the person is gone, the honest record is “not known, and here is why”.

Derive the half that is derivable.

Components, dependencies, interfaces, data flows and an explicit list of what could not be established — from one read-only instruction, without occupying anybody for a quarter.

Build your project map — free Why documentation decays