Most technical documentation is written for the wrong reason. It's written so that, if anyone ever asks "is this documented?", the answer is technically yes. It exists to have existed. Nobody reads it, because it wasn't written to be read — it was written to close a ticket. And a migration is where that failure costs the most, because a migration is precisely the moment someone unfamiliar has to understand a system fast, often under pressure, often at the worst possible time.
I've been documenting a migration, and I've tried to write the other kind — the kind meant to actually help the human who inherits it. Given my background is in communication before it was in data, this is the post where those two halves of me finally shake hands. Here's what I've learned about doing it properly.
Write for the person, not the ticket
The single shift that changes everything: picture the actual reader. Not "documentation" in the abstract — a specific, stressed human, six months from now, who has to understand your migration because something's gone wrong and you're on holiday. Everything else follows from taking that person seriously.
That person doesn't need a transcription of every step you took. They need to understand the shape of what happened and be able to find the specific detail when they need it. Which means the two most valuable things you can write are the two things dumped-out documentation always omits:
- The why. Anyone can eventually reverse-engineer what you did from the code and the scripts. What they can't recover is why — why this approach over the obvious alternative, why this thing was left as it was, why that seemingly-odd choice was actually deliberate. The "why" is the expensive knowledge, and it's the first thing lost when it isn't written down. Document decisions, not just actions.
- The gotchas. The traps you fell into and climbed out of. The step that looks optional but isn't. The thing that has to run before that other thing or everything breaks. This is the hardest-won knowledge you have, and it's worth more to your successor than any tidy diagram.
Structure so people can find things under stress
A wall of prose is unreadable at 2am, no matter how good the content. Structure isn't decoration — it's what makes documentation usable when the reader is panicking and skimming.
- Lead with a map. Start with a short overview of the whole migration — what moved, from where to where, in what order. One page that lets someone orient themselves before they dive. If a reader can't get the shape of the thing in two minutes, they'll give up and just ask you, which defeats the purpose.
- Make it skimmable. Headings a stressed person can scan to jump straight to their bit. The reader in trouble isn't reading start to finish — they're hunting for the one section they need. Build for the hunt.
- Write runbooks for the things that recur. For anything someone will actually do — run the cut-over, roll back, re-run a failed load — give them a clean numbered procedure, not a paragraph they have to decode into steps while the pressure's on.
Say what you don't know, and what could still bite
The most trustworthy documentation admits its own edges. If there's a part of the migration you're unsure about, a known risk, a bit of the old system nobody fully understood — write that down explicitly. A confident document that hides its uncertainty is worse than useless, because it sends the next person down a false trail with full confidence. "We're not certain how the legacy job handles leap years — watch this in February" is one of the most valuable sentences you can leave behind.
Good documentation isn't a transcript of what you did. It's a briefing for the person who has to carry on without you in the room.
The skeleton I now use
To make this concrete, here's the actual shape of a migration document I'd be happy to hand to a stranger. It's not elaborate — being usable matters far more than being exhaustive:
- Overview — one page: what moved, from where to where, in what order, and why we did it at all. The map.
- Key decisions — the why behind the approach, and the alternatives we rejected. The expensive knowledge that can't be recovered from the code.
- How it's built — the components, in plain language, with pointers to where the real detail (code, scripts) lives rather than transcribing it.
- Runbooks — clean numbered procedures for the things someone will actually do: run the cut-over, roll back, re-run a failed load.
- Gotchas & open risks — the traps, the ordering dependencies, and an honest list of what we're not sure about.
The order is deliberate: someone in trouble reads top-down and gets more specific as they go, bailing out at the level of detail they need. Nobody has ever complained that a document was too easy to navigate under pressure.
Why this is really the same job I've always done
Here's the thread I keep pulling in everything I write: this is a communication problem, not a technical one. Documenting a migration is encoding your understanding so it survives the trip into someone else's head — which is exactly what communication is. It's the same instinct I had back in my research days, turning thousands of articles into data by hand: the meaning is only as good as how faithfully you encode it for whoever reads it next. The same discipline I'd apply to any message applies here: know your reader, lead with what matters, structure for how they'll actually consume it, and be honest about what you're not sure of.
The engineers who write genuinely useful documentation aren't necessarily the best engineers. They're the ones who remember there's a human on the other end, and write for that human instead of for the ticket. In a field that treats documentation as a chore to be survived, being the person who writes the version people actually thank you for is a quietly enormous advantage. It's also, I've come to think, the most honest expression of caring about the work — because it's the part of the work that only helps other people.