Imagine a Monday morning, 8:40 a.m. The sales dashboard hasn’t refreshed: the overnight job failed. The person who has to step in has the code and the access, but didn’t build the system. Before the 10 a.m. meeting, they need to find out which data is missing, decide what to rerun, and check that the numbers are right.
How long will it take them? And how many of the answers exist only in the head of the person who built the platform?
To me, this question is part of delivery quality, just like getting the numbers right. A well-delivered platform lets someone who knows the stack take over day-to-day operations without constantly relying on its designer. They will have a business to learn and an architecture to understand. Finding a decision, identifying a dependency or rerunning a job shouldn’t require digging through old message threads.
Handover is decided in the architecture
On a BigQuery and dbt stack, reading the SQL tells you the transformations. To run the system, you also need to know how data comes in, what triggers each job, which access is required and how errors are surfaced.
So I apply the same conventions everywhere. If ten sources are loaded the same way, understanding the first one gives you a map for the other nine. An exception is sometimes justified; it is then named and explained where you run into it.
For day-to-day operations, I put the coherence of the whole ahead of optimizing each component. A custom connector can perform better in isolation and still cost hours to the person running it alongside everything else.
Same logic for tools. Every added component is something to understand, configure, maintain and pay for. I add one when I can say what need it covers and why what’s already there can’t handle it.
And before documenting a complicated architecture, I try to simplify it.
Document what the code doesn’t say
I don’t paraphrase SQL in plain English. I document what reading the code can’t tell you with certainty: decisions and limitations.
Take a confirmed-orders metric. A filter on the status is perfectly readable. It doesn’t say whether the model describes the order’s current state or an event in its history, why confirmation was chosen over shipping, or which team set the rule. Without those answers, the next person can’t tell whether they’re looking at a deliberate rule or a bug, or who to talk to before changing it.
Here is a fictional example of a documented rule:
Counted order: any order that has been confirmed at least once, counted on the date of its first confirmation, based on the status history.
Why: marketing tracks confirmed orders without waiting for them to ship.
Consequence: a later cancellation doesn’t remove the confirmation from this metric. Cancellations and net revenue are tracked separately.
Business owner: marketing leadership.
Limitations get the same treatment. A source’s API only returns part of the history. A period could never be recovered. A file still has to be dropped in manually every month. I keep them in a single place, each with its practical consequence, because a limitation discovered in the middle of an incident slows down the diagnosis and makes recovery harder.
Hand over what’s needed to act
The person taking over also needs to be able to intervene.
A procedure titled “Rerun the job” is only useful if it says when to rerun and what the rerun will do. Does it replace a period’s data? Fill in the gaps? Could it create duplicates? What needs checking afterwards?
Simplified example: recomputing one day of orders
Before acting: check that the day’s raw data is complete and that no concurrent job is running. If it’s incomplete, restore the load from the source first.
Expected effect: in this example, the job replaces the data for the chosen day; running it again doesn’t add the data a second time.
How to run it: to be specified in the runbook — command or workflow to launch, expected parameters, target environment.
After running: check expected volumes, order uniqueness and that the dashboard has refreshed.
Stop and ask for help: if the prerequisites aren’t met or the checks keep failing.
Checks follow the same standard. A job that ran without errors doesn’t guarantee the expected data is there. I separate execution checks from content checks (volume, freshness, uniqueness) and write down what each one covers.
Access is part of the handover. Who administers the cloud project? Who can grant a permission? Who owns the service account that connects to the e-commerce tool? These answers need to be written down somewhere, so operations don’t depend on one person being available.
Finally, each reader gets their own level of detail. The person running the business needs to know the critical dependencies and the impact of an incident. The person stepping in needs the procedures and the access.
On a tight budget, I protect what’s critical first
All of this takes time, and a small team can’t invest it everywhere. I allocate effort along two separate criteria: the impact of an error, and the effort needed to recover.
| Easy to rebuild | Hard to reconstruct | |
|---|---|---|
| Low-cost error | a convention, one line | the source and its limitations described |
| Costly error | checks and a short recovery procedure | written rule, checks, tested procedure |
The two axes are read separately. An intermediate table rebuilt in ten minutes is still critical if it feeds a budget decision. A rarely used history deserves particular attention if it’s impossible to recover.
This trade-off is written into the project scope. If a first version requires a manual step, I specify which one, who does it and what remains to be automated. The client decides with full knowledge. I’m happy to deliver a smaller scope whose operation is under control.
The documentation itself follows this principle. Every important piece of information has a single home, and I treat updating an explanation as part of changing the rule it describes. A few well-maintained pages are worth more than an exhaustive folder where no one knows what’s still true.
Delegate without being locked in
An SMB may choose to hand over the long-term operation of its platform to a provider rather than build an in-house team. That choice shouldn’t reduce its ability to reorganize later.
That’s exactly where handover capability matters. It’s what lets the client evolve its organization: hire a first in-house person, hand part of the scope to another provider, commission an independent audit.
I want my clients to keep working with me for the quality of the work and my knowledge of their business, knowing what they delegate and what a change would involve.
Not every dependency goes away. A platform relies on services, libraries, sometimes specific components, and switching them takes work. Critical dependencies are identified, along with what replacing them would involve: what would need to be migrated, rewritten or reconfigured.
Make handover an acceptance criterion
To me, handover capability should be part of project acceptance. One way to check it is to give a few defined tasks to someone who didn’t build the system. They should be able to:
- find the definition of a metric;
- identify the job that feeds it;
- check its freshness;
- follow the rerun procedure in a test environment;
- make a small change and deploy it.
Then you watch where they get stuck. A missing step, an access no one can locate, an ambiguous rule each become a precise fix. The exercise scales with the project and complements testing and training.
The code, models and jobs are part of the delivery. So is the next team’s ability to understand, run and evolve them.