The handover that actually worked, and the four I botched first
A handover is not a document dump. The test is whether the team ships without you in week one.
TL;DR
My first four handovers were a 20-page document, a two-hour walkthrough, and a cheerful "message me if anything comes up". All four produced the same result: a month of unpaid Slack questions, and in two cases a request to come back and fix something I had explained in week one.
The fifth one worked, and the difference was a single change: instead of explaining the system, I had a member of their team ship a real change while I watched and said nothing useful. Three times, on three different parts of the system, before I left.
The test of a handover is not whether you explained it. It is whether they can do it — and that is only observable by having them do it.
The case this post is about
Handover four, which was my best attempt at the document approach:
HANDOVER.md 21 pages
architecture overview 4 pages, with diagrams
module-by-module walkthrough 9 pages
deployment runbook 3 pages
known issues and gotchas 3 pages
"who to ask about what" 2 pages
walkthrough call 2 hours, recorded
Q&A session 1 hour
Thorough by any reasonable standard. The team said it was the best handover they had received.
The symptom
Thirty-one Slack messages in the following five weeks:
week 1 11 messages "where does X live", "how do I regenerate Y"
week 2 8 messages "the sync is doing something odd"
week 3 6 messages "can you look at this PR?"
week 4 4 messages "we broke the iOS build"
week 5 2 messages
About nine hours of unpaid time, and I answered all of it because the alternative was a bad reference.
And the content of the questions was the finding:
answered in HANDOVER.md: 19 of 31 (61%)
answered in the recording: 7 of 31
genuinely new: 5 of 31
Sixty-one percent of the questions were answered in a document they had read and praised. Not because they were careless — because reading an explanation does not produce the ability to act, and under time pressure asking me was faster than searching 21 pages.
The two call-backs:
"the sync queue is dropping items" → they had changed the bounded channel's
overflow policy, which page 14 explains
"the iOS framework won't link" → a target had been removed from the shared
module; page 17 covers the target list
Both were covered. Both recurred. I had transferred information and not capability.
Why the obvious things did not work
"Write a better document." Twenty-one pages was already too long to search under pressure, and the questions were in it. Length was the problem, not the remedy.
"Record more video." The recording answered seven questions and nobody watched it after week one. Video is worse than text for the "where is X" question, which is most of them.
"Hold a longer Q&A." A Q&A answers the questions people can think of while sitting in a meeting. The real questions arrive in week two, with a deadline attached, in a context the meeting did not cover.
"Charge for the post-handover support." I did this on handover three — a retained 2 days/month. It is a reasonable commercial arrangement and it made the dependency permanent rather than transferring it, which is the opposite of the goal.
The actual mechanism
A handover transfers two different things, and I was only doing one:
Information — where things are, how they work, why decisions were made. A document transfers this adequately, and it is the easy half.
Capability — the ability to make a change, verify it, and ship it. This is procedural knowledge, and reading about it does not produce it. It is produced by doing it, with the failure modes encountered and recovered from.
The second one has a property the first does not: it is testable. "Did I explain the deployment process" is unfalsifiable. "Did Priya deploy to staging, unaided, while I sat on a call and said nothing" has a yes or no answer.
Written down, a handover plan is therefore a list of capabilities with a pass condition each, and the scoring rule is what keeps it honest:
from dataclasses import dataclass, field
@dataclass
class Task:
capability: str
attempts: list[str] = field(default_factory=list) # "unaided" | "prompted" | "took-over"
@property
def verdict(self):
if not self.attempts:
return "untested"
# Only the LAST attempt counts, and only "unaided" passes. A task I talked
# someone through is evidence that I can explain it, which is the thing that
# was never in doubt.
return "transferred" if self.attempts[-1] == "unaided" else "not-yet"
def readiness(tasks, days_left):
untested = [t for t in tasks if t.verdict == "untested"]
not_yet = [t for t in tasks if t.verdict == "not-yet"]
for t in tasks:
print(f" {t.verdict:<12} {t.capability:<34} {' → '.join(t.attempts) or '—'}")
if untested:
# An untested capability is the dangerous category: it looks like the others
# on a document, and nothing has demonstrated it. Never count it as covered.
return (f"NOT READY — {len(untested)} capability(ies) never attempted, "
f"{days_left}d left. Schedule these first; they need two attempts each.")
if not_yet:
return f"NOT READY — {len(not_yet)} need another unaided attempt"
return "READY"
With four days left, scored against what had actually happened:
transferred deploy to staging prompted → unaided
transferred roll back a bad release took-over → prompted → unaided
not-yet rotate the signing certificate prompted
untested restore from backup —
untested on-call escalation path —
NOT READY — 2 capability(ies) never attempted, 4d left. Schedule these first;
they need two attempts each.
Two of five had never been attempted, and both were in the handover document in full prose — which
is exactly why the document felt complete. The took-over → prompted → unaided progression on the
rollback row is the shape this is looking for, and it took three sessions; the two untested rows
needed at least two sessions each, which is a scheduling fact a document cannot surface.
And there is a specific trap in the explanation mode: as the person who built it, I answer questions in about thirty seconds, so asking me is always cheaper for them than developing the capability. Every answered question reinforces the dependency, which is why the Slack volume decayed slowly rather than stopping.

Explaining a system is unfalsifiable. Watching someone use it is a test. A handover without that test has transferred information and left the capability with you.
The fix
Three supervised changes, a one-page document, and a silence rule.
1. Three real changes, shipped by them, in the last week:
## Handover exercises (week 12, with me present and silent)
1. A small feature change end to end
→ add a "retry now" action to the sync screen
Must: write it, test it, get it reviewed, merge it, deploy to staging.
2. An incident
→ I break staging on Tuesday morning without telling them which part.
Must: diagnose it from the logs and dashboards, fix it, deploy.
3. A dependency and release task
→ bump the Ktor version and produce a release build for both platforms.
Must: handle the two breaking changes, run the full matrix, sign the iOS build.
Three exercises, chosen because they cover the three things the previous handovers' questions clustered around: making a change, diagnosing a problem, and releasing.
2. The silence rule, which is the hard part:
## My role during an exercise
I am on the call with my microphone muted. I do not answer questions during the
exercise. If they are stuck for more than 20 minutes, they say so and I give
ONE pointer — to a document or a file, never an answer.
Afterwards we debrief: what was hard, what was missing, what should the
document say.
Twenty minutes of being stuck is where the learning is, and answering at minute three is the habit I had to break. The "one pointer, to a document" constraint is what converts a stuck moment into a documentation fix rather than into another answer only I can give.
3. The document, which got shorter because the exercises told me what belonged in it:
# Handover (1 page)
## Start here
`./scripts/setup.sh` — if it fails, that is a bug, file it.
## The three things you will need in month one
1. Making a change → docs/making-a-change.md (written by Priya after exercise 1)
2. When it breaks → docs/runbook.md (written by Tom after exercise 2)
3. Releasing → docs/release.md (written by Priya after exercise 3)
## Decisions you will want the reasons for
docs/adr/ — 14 records. Read 003 (sync queue) and 011 (why SQLDelight) first.
## Things I would do next, in priority order
1. … 2. … 3. … (my opinion, not a commitment)
They wrote the three procedural documents, not me. That is the detail that made them useful: written by someone who had just done the task for the first time, so they contain the steps a newcomer actually needs rather than the steps I could not see because I knew them.
4. And a bounded support window, stated in the contract:
## Post-engagement support
Two weeks of email support, up to 2 hours total, included.
After that: £400/day, minimum half a day, scheduled.
Bounded and priced rather than open-ended and free. The two-hour limit also gave them a reason to check the document first, which is the behaviour the exercises were building.
How this turned out
Handover five, against the previous four:
handovers 1–4 (mean) handover 5
pages of documentation 18 1 + 3 (theirs)
my hours in the handover week 6 12
Slack messages, first 5 weeks 27 4
my unpaid hours after leaving ~8 0.5
call-backs for paid rework 0.5 (2 of 4) 0
Twelve hours instead of six during the week — the exercises cost me time — and 0.5 unpaid hours afterwards instead of eight.
The four questions in five weeks:
week 1 "is ADR-007 still accurate?" → yes (2 min)
week 2 "we're adding a target, anything to know?" → pointed at ADR-011 (5 min)
week 4 "would you do X or Y here?" → an opinion, 20 min
week 6 "thanks, all good"
None was "where does X live". The procedural questions were gone, because they had done each of the three things once.
The exercises themselves, which is where the real value showed:
exercise 1 (a feature change)
time: 3.5 hours · stuck twice · 1 pointer used
found: the PR template referenced a lint rule that had been removed
→ fixed, and it is in making-a-change.md
exercise 2 (the incident)
time: 1 hour 10 min to diagnose, 25 min to fix · 0 pointers
found: the runbook did not exist; Tom wrote it from what he had just done
→ runbook.md, 1 page, written by the person who needed it
exercise 3 (dependency bump + release)
time: 5 hours · stuck three times · 2 pointers
found: the iOS signing step required a credential only I had
→ moved into the team's vault before I left. This would have blocked
their first release entirely.
Exercise 3 is the one that justifies the whole approach: a credential only I had would have stopped their next release, and no amount of documentation review would have surfaced it. Having someone actually do the release found it in five hours.
One honest limit: this requires the client to allocate two people for roughly two days in the final week, and one engagement since has refused — the team was mid-crunch and could not spare them. I documented the exercises as not done in the handover note and set expectations accordingly, and that handover produced 14 Slack messages. The method works; it needs the client's time, and when they cannot give it, saying so plainly is the next best thing.
What this generalizes to
Explaining is unfalsifiable; observing is a test. This applies to onboarding, to teaching, to training a successor, to any documentation of a process. "Did they understand" has no answer. "Did they do it unaided" does.
Let the person who just learned it write the document. They know which steps are non-obvious, because they were non-obvious an hour ago. An expert writing a procedure omits exactly the parts that make it hard.
An available expert prevents capability transfer. Answering in thirty seconds is always cheaper for the asker than learning, so availability sustains dependency. Being deliberately slow, or silent, is the mechanism — and it is uncomfortable.
The gap you cannot document is the one only an attempt finds. A credential only I held, a lint rule that no longer existed, a missing runbook. None would have appeared in a review of my documentation, and all three appeared within five hours of someone trying to do the work.
Related
- The onboarding doc that doubled as a test of our own setup — the same executable-documentation idea, internally
- The architecture decision nobody wrote down, re-litigated four times — the ADRs this handover points at
- Scope creep is a contract problem, not a communication problem — bounding the support window
Keep reading
This is part of Freelancing & consulting for engineers — the commercial side of the work, written from the mistakes. Follow MobileByteSensei for the rest.
One post a week, no digest
New writing when it lands. No roundups, no course pitch, no "10 tips".