How to Document a Legacy System
To document a legacy system you no longer fully understand, work from the code outward rather than from memory: prioritize by risk and change-pressure, recover behavior with an AI-accelerated deep-read, validate the drafts with the engineers who remain and against the running system, and capture the result as living specs tied to the code. Don't try to document everything at once or wait for a complete picture before acting — document the highest-risk areas first, in the form that stays current, while the people who understand them are still there to confirm what you've captured.
Across this series we’ve defined the problem — tribal knowledge and documentation drift — counted its cost, named the clock, and described the recovery and the durable form it takes. This final part is the playbook: how to actually document a legacy system you no longer fully understand, in the right order, without stalling and without producing something that drifts the moment it ships. It’s where the whole series turns into a plan you could start on Monday.
First, reject the two instincts that fail
Most legacy-documentation efforts die one of two deaths, and both come from a reasonable-sounding instinct. Name them up front so you can refuse them.
The first is document everything, uniformly. Faced with a system no one fully understands, the urge is to be thorough — start at the top and work through it all. This reliably runs out of budget and energy in the safe, easy areas and never reaches the dangerous ones, because the dangerous areas are dangerous precisely because they’re hard. You spend the effort where it’s pleasant and stop before where it matters.
The second is document it all before changing anything. This feels prudent — understand fully, then act. In practice it stalls indefinitely: a complete document of a large system is a moving target the system won’t hold still for, and the business can’t wait years for understanding before it gets value. The freeze-then-rebuild instinct is the same one behind the big-bang failures the whole discipline exists to avoid.
The working principle is the opposite of both: document by risk, interleaved with change. Go deep where it’s dangerous, in the form that stays current, alongside the work that uses it.
Step 1: Map and prioritize by risk
Before recovering anything in depth, build a coarse map of the system and rank it. You’re not documenting yet; you’re deciding where to document first.
The ranking that matters crosses two axes:
- Bus factor — how few people could safely change this subsystem. One is a red flag; zero is a fire.
- Change-pressure — how likely the business is to need this area changed or modernized soon, whether for a roadmap feature, a compliance deadline, or an end-of-life runtime.
Where a low bus factor meets high change-pressure, document first — that’s where lost knowledge will hurt soonest and most. A subsystem that only one near-retirement person understands but that the business will never touch can wait; one that two people understand and the next big project depends on cannot. This is the same triage that drives a modernization roadmap, and it’s the step that keeps the effort honest: it forces you to act on the dangerous areas first, when the instinct is to warm up on the safe ones.
Step 2: Recover behavior from the code
For each prioritized area, recover what the system actually does — from the code, because the code is the one current and complete record, while the docs have drifted (Part 2) and memory has gaps (Part 4).
At any real scale this is where an AI deep-read earns its place. Reading the whole of a subsystem — code, copybooks, stored procedures, config, and what docs exist — and drafting its behavior is exactly the comprehension-at-scale work that defeats manual review on budget. The analysis that took twelve weeks takes about two. The output is draft specs: the call graph, the data flows, the edge cases, and the candidate business rules, each traceable to the code it came from. Drafts, not verdicts — which is exactly what the next step is for.
Step 3: Validate with the people, while you still can
Drafts recovered from code answer what. They don’t answer why, and they can be wrong. Step 3 closes both gaps using the source that’s most perishable: the people who still understand the system.
This is the inversion from Part 4, and it’s the highest-value hour in the exercise. Don’t ask experts to recall everything from a blank page — show them the draft and ask them to react. They confirm what’s right, correct misread intent, flag dead branches, and supply the why behind the rules that look arbitrary: the incident, the regulation, the one big customer. Reacting to a concrete draft surfaces the situational knowledge that interviews never reach, and it produces a reviewed artifact rather than a transcript. Do this while the experts are present — it’s the step you cannot do later, and the schedule is set by their careers, not yours.
Step 4: Prove it against the running system
A reviewed spec is a strong artifact, but reviewed is not the same as proven, and the difference is where the expensive surprises live. For anything you’re about to modernize, hold the recovered behavior to the running system through parity validation: run the modern slice on shadow traffic alongside the legacy and compare. Every divergence is a gap in your captured knowledge surfacing as a ticket — before a user feels it, not after cutover. This is what lets you stand behind the documentation as true rather than believed.
Step 5: Capture as living specs, not a one-time document
Finally, store what you’ve recovered in the form that doesn’t drift. A one-time document, however thorough, starts drifting the day it ships — the same decay that produced the problem in the first place. Capture it instead as living specs: tied to the code, proven by parity, and updated by the same work that changes the system, so staying current is the path of least resistance rather than a separate task that loses to every deadline. Document once, in a form that stays true — otherwise you’re just scheduling this whole exercise to be repeated in five years.
The playbook, in order
| Step | Question it answers | Primary source |
|---|---|---|
| 1. Map & prioritize | Where do we document first? | Bus factor × change-pressure |
| 2. Recover behavior | What does it actually do? | The code (AI deep-read) |
| 3. Validate with people | Is this right, and why is it here? | The remaining experts |
| 4. Prove against the system | Does it match reality under load? | Parity validation |
| 5. Capture as living specs | How does it stay true? | Specs tied to the code |
Read top to bottom and the order isn’t arbitrary: each step feeds the next, and each is positioned where its source is strongest — code for what, people for why, the running system for proof, coupling for durability.
What to actually capture, by kind
The five steps set the order and the method. They don’t yet say what a finished capture contains. A legacy subsystem hides its knowledge in five different places, and each needs its own artifact, its own best source, and its own form. Recover behavior and you’ve answered what runs, but you still haven’t written down what the fields mean, what the system talks to, or what happens at 3am when it stops. Miss any one kind and it resurfaces later as the thing nobody wrote down.
| Artifact | What it captures | Best source | Form it lives in |
|---|---|---|---|
| Behavior spec | What the code does: call graph, data flows, the edge cases | The code, via AI deep-read | Living specs tied to the code |
| Data dictionary | What each field means, which store is authoritative, what’s still used | Schema plus code plus the people | Versioned alongside the schema |
| Integration map | Every upstream and downstream system, the contracts, the batch feeds and their timing | Config, connection strings, job schedulers, ops logs | Architecture doc or living spec |
| Business-rule catalog | The conditions and thresholds the logic enforces, and the why behind each one | Code drafts reacted to by the experts | Rules traceable to the code that runs them |
| Operational runbook | How it deploys, how it fails, how it recovers: the knowledge that lives in one operator’s head | The people who run it, not the code | A runbook kept next to the system |
Two of these come mostly from the code and two mostly from the people, which is why Steps 2 and 3 stay separate. The data dictionary sits between them: the code shows which columns get read and written, but only a person knows that status = 7 marks a case a regulator once cared about. Work the table left to right and the risk map from Step 1 tells you which area to fill first. You don’t produce all five for the whole system. You produce the set the highest-risk slice needs before you modernize it.
Documentation is a means, not an end
This playbook documents a system in order to use the documentation — to modernize safely, to lower the bus-factor risk, to keep changing the system with confidence. It is not a case for documentation as an end in itself. For a stable system under no change-pressure that the business will never touch, the most honest answer may be to document lightly, or not at all, and spend the effort where something is actually going to change. And no method, this one included, can recover knowledge that exists nowhere — not in the code, not in a living person, not in any record. Where that’s the situation, the honest move is to say so, preserve the behavior exactly because you can’t justify changing what no one understands, and stop pretending a document can contain what was already lost. Documentation is the means here, never the trophy.
Where this leads — and what to do next
This is the last part of the series, so the thread closes where Part 1 opened: most organizations don’t fully know what their most critical systems do, and the knowledge is leaving on a clock. The five steps above are how you change that — recover from the code, validate with the people, prove against the system, and capture it in a form that stays true and that your team owns.
If your situation is the one this series keeps describing — a system the business depends on, a thinning group who understand it, and pressure to change it — the most useful next step is a focused conversation about your specific estate. Our discovery process is built to do exactly the capture this playbook describes, at speed and under senior-engineer review. Book a 30-minute discovery call — no deck, just a conversation about what your system actually does, and who still knows. If you would rather start in writing, reach us at sales@modernlift.ai.
Frequently asked questions
- Where should you start when documenting a legacy system?
- With the areas of highest risk and highest change-pressure, not with whatever is easiest or first alphabetically. Rank subsystems by bus factor (how few people understand them) crossed with how likely the business is to need them changed. Start where a low bus factor meets real change-pressure — that's where lost knowledge will hurt soonest. Trying to document everything uniformly spreads effort thin and tends to finish the safe areas before reaching the dangerous ones.
- Should you document the whole system before modernizing it?
- No — and waiting to is a common way to stall. Documentation and modernization work best interleaved: document a slice deeply enough to modernize it safely, prove it, move on. A complete document of an unchanging system is rarely worth the wait, and the system won't hold still for it anyway. Capture comprehensively where you're about to act, and keep the rest as a prioritized map until its turn comes.
- What should legacy system documentation actually include?
- Five kinds of artifact, because a legacy subsystem hides its knowledge in five different places. A behavior spec (what the code does: call graph, data flows, edge cases), a data dictionary (what each field means and which store is authoritative), an integration map (every upstream and downstream system, feed, and its timing), a business-rule catalog (the conditions the logic enforces and the why behind each), and an operational runbook (how it deploys, fails, and recovers). The first two come mostly from the code, the rest mostly from the people who still run it. You produce the set the highest-risk area needs before you touch it, not all five for the whole system at once.
- How do you keep legacy documentation from drifting again?
- By making it living documentation — tied to the code and the validation process so it updates with the system instead of depending on a separate manual step. A one-time documentation effort, however thorough, begins drifting the day it ships, exactly as the original docs did. Generating the documentation from the code, proving it against the running system, and updating it as part of the work that changes the system is what stops the drift cycle from restarting.