The script is the least valuable thing the author leaves behind. Anyone can read a crontab line or a schedule: field. What the next on-call engineer cannot reconstruct from the script is what normal looks like, which failures are silent, what a partial run corrupts, and what to check first when the output is empty. That knowledge lives in the author’s head, and it is the actual handoff.
This is a procedure for extracting it. It treats the departing author’s cron job as a failure-mode inventory rather than a code review, and it borrows the structure of postmortem and runbook craft that already exists for larger teams. The scale is different — two to fifteen engineers, no dedicated SRE, the same people on call who write the code — but the documentation problem is the same one Google’s SRE book describes: an incident record exists so that the next person does not rediscover the failure from scratch.
Start with the failure inventory, not the rewrite
The instinct when an owner leaves is to schedule a rewrite. Resist it for the handoff window. A rewrite is a project; a failure inventory is an afternoon, and it is what makes the job survivable in the meantime.
List every way the job can fail, and for each one write what it looks like from outside the process. A working inventory for a scheduled job usually covers:
- Silent no-op. The process exits zero but wrote nothing, because an upstream query returned no rows, a filter matched nothing, or a feature flag disabled the work.
- Partial write. The job processed some records and died, leaving a half-updated table or a partially uploaded object.
- Overlapping run. A slow run is still going when the next schedule fires, and two processes write the same rows.
- Missed schedule. The scheduler did not fire, or fired late, and the job’s assumptions about the previous run’s state no longer hold.
- Credential expiry. A token, key, or certificate rotated or expired and the job failed at authentication.
- Upstream dependency down. The database, API, bucket, or queue the job reads from was unavailable or slow.
For each entry, the author should write three things: how you would notice it, what it damages if left alone, and the first check a responder should run. If the author cannot answer “how would you notice it,” that is itself the finding — the failure mode is currently invisible, and the handoff should say so plainly rather than imply coverage that does not exist.
Borrow the postmortem lens for failures that have not happened
Google’s SRE book defines a postmortem as “a written record of an incident, its impact, the actions taken to mitigate or resolve it, the root cause(s), and the follow-up actions to prevent the incident from recurring.” That structure is retrospective by convention, but nothing about it requires the incident to have happened yet. For a handoff, fill in the same sections as a pre-mortem: for each failure mode in the inventory, write the trigger, the impact, the detection signal, the recovery steps, and the action item that would prevent recurrence.
The SRE book also lists common postmortem triggers, including data loss of any kind, on-call intervention, and monitoring failure — the last of which “usually implies manual incident discovery.” Those triggers map directly onto cron job failure modes. A job that silently stops writing is a monitoring failure by definition. A job that duplicates rows is data loss in the sense that matters to the downstream consumer. Writing the trigger conditions down before the incident means the next on-call does not have to decide, at 2 a.m., whether this counts as an incident worth escalating.
Two craft notes from the SRE Workbook apply with unusual force to a handoff document. First, the workbook’s critique of a bad postmortem notes that its Recovery Efforts section was left empty — the record of what was actually done to fix things was missing. A handoff doc with a failure inventory but no recovery steps has the same defect. Second, the workbook recommends a single owner rather than several, because “an owner is a single point of contact who is responsible for the postmortem, follow-up, and completion.” A handoff document with four names on it and no review date is a document that will rot. Name one owner and set a review date.
Separate “did it run” from “did it work”
The most dangerous failure mode for a lean team is the one that pages no one. A cron job that exits zero and writes nothing produces no alert, no error log, and no obvious symptom until a downstream consumer notices stale data — sometimes days later. The handoff must include a success check that is independent of the exit code.
What that check looks like depends on the job, but the shape is consistent: assert something about the output that would be false if the job had not done its work. A row count in a target table. A timestamp in a heartbeat table. A file’s presence and modification time in a bucket. The point is that the check must be runnable by someone who did not write the job, and it must fail loudly when the job silently no-ops.
This is where the handoff document earns its keep. The author knows which query returns zero rows on a quiet day and which returns zero rows because something broke. The next person does not. Write down the difference.
Document the blast radius explicitly
The information the next on-call needs most urgently is also the information the author is most likely to omit: what the job touches. Which tables, buckets, queues, or downstream consumers does it write to? What does a partial run leave behind? What does a duplicate run corrupt?
For a job that writes to PostgreSQL, this means naming the tables and the write pattern — insert, upsert, delete-then-insert — because the recovery procedure differs for each. For a job that writes to object storage, it means naming the bucket and prefix and whether a re-run overwrites or appends. For a job that publishes to a queue, it means naming the consumer and whether duplicate messages are idempotent on the receiving end.
The blast radius section should also state what the job does not touch. A responder who knows the job only writes to one table will not waste time checking the others. Negative information is cheap to write and expensive to reconstruct.
Capture the schedule’s assumptions, not just the expression
A cron expression without its assumptions is a trap. The expression says when the job fires; it does not say what timezone the schedule is interpreted in, how long a normal run takes, what happens when a run is late, or whether overlapping runs are permitted.
Platform documentation makes the timezone assumption concrete. Google Kubernetes Engine’s CronJob documentation states that “all CronJob times are in UTC” and that the schedule uses five-field crontab format. Amazon EventBridge’s scheduled rules documentation states that “all scheduled events use UTC+0 time zone, and the minimum precision for a schedule is one minute.” If the author wrote the schedule thinking in local time and the platform interprets in UTC, the handoff should say so — and the next person should verify the actual fire times rather than trust the expression.
Overlap policy is the other assumption that bites. GKE’s documentation notes that if startingDeadlineSeconds is empty, the CronJob never times out, “which could lead to the same CronJob running multiple times simultaneously,” and that concurrencyPolicy defaults to Allow, meaning concurrent jobs are permitted. A homegrown job on a bare-metal crontab has no such policy field; overlap prevention is whatever the script does, or does not do. The handoff should state which it is.
Expected duration matters for the same reason. If a normal run takes four minutes and the schedule fires every five, a slow run overlaps. If a normal run takes forty minutes and the schedule fires hourly, the margin is thin. Write down the observed duration range, not the author’s recollection of it.
Write the runbook as decision points, not a command list
A list of commands tells the next person what to type. It does not tell them when to type it, when to stop, or when to escalate. Runbook guidance from the operations literature converges on the same structure: purpose, scope, trigger conditions, prerequisites, step-by-step instructions, validation, rollback, escalation, and revision history. For a cron job handoff, the decision points are the part that matters most.
For each failure mode, the runbook should answer:
- What do I check first, and what does each outcome tell me?
- When is it safe to re-run, and when will a re-run make things worse?
- What is the stop condition — the point at which I should stop investigating and escalate?
- Who do I escalate to, and what do they need to know?
The re-run question deserves special attention. A job that is idempotent can be re-run freely; a job that appends or increments cannot. The handoff should state which it is, and if the answer is “it depends on where it failed,” the runbook should say where.
Verify the backup and restore path the job depends on
If the job writes data that matters, the handoff is incomplete without a tested restore path. This is where lean teams most often discover, during a handoff, that the backup was never verified.
The tools have verification commands, and the handoff should name them. restic’s documentation describes a check command for checking repository integrity and consistency. pgBackRest’s user guide explains that incremental backups depend on prior backups being valid to restore — “all prior incremental backups back to the prior differential, the prior differential backup, and the prior full backup must all be valid to perform a restore of the incremental backup” — which means a handoff that documents only the latest backup is documenting an incomplete recovery path. The same guide notes that local and remote pgBackRest versions must match exactly, or WAL archiving and backups will not function; a version mismatch discovered during a restore is a bad time to learn it.
The handoff should include a restore rehearsal, not just a restore procedure. The rehearsal can be small: restore the most recent backup to a scratch instance, run the success check against it, and record the result. A procedure that has never been executed is a hypothesis.
Prefer a guard over a warning
The SRE Workbook’s critique of a bad postmortem includes an action item to “train humans not to run unsafe commands,” and the workbook’s response is direct: “In general, trying to change human behavior is less reliable than changing automated systems and processes.” The same principle applies to the handoff. If a failure mode is likely, the handoff should include a proposed guard — a lock file, a pre-flight check, an alert on the success check — rather than a note that says “be careful.”
A guard is also easier to verify. A note that says “do not run this twice” depends on the next person reading the note. A lock file that prevents a second run depends on nothing. Where the author can add the guard before leaving, that is worth more than a paragraph describing the hazard.
What the handoff document should contain
A workable structure, adapted from the runbook and postmortem guidance above:
- Purpose and scope. What the job does, what it does not do, and which environments it runs in.
- Schedule and assumptions. The expression, the timezone it is interpreted in, observed duration range, overlap policy, and what happens when a run is late or skipped.
- Failure inventory. Each failure mode, how it is detected, what it damages, and the first check.
- Success check. The independent verification that the job did its work, runnable by someone who did not write it.
- Blast radius. Tables, buckets, queues, and downstream consumers touched, with the write pattern for each, and what is explicitly not touched.
- Runbook. Decision points for each failure mode: first check, re-run safety, stop condition, escalation path.
- Backup and restore. The verification command, the restore rehearsal result, and the version-match requirement if applicable.
- Owner and review date. One name, one date.
The document does not need to be long. It needs to be specific enough that the next on-call can act on it without calling the author, and honest enough to say where coverage is missing. A handoff that says “we do not currently detect the silent no-op case” is more useful than one that implies detection exists.
Frequently asked questions
How long should the handoff document be?
Long enough to cover the failure inventory and the runbook decision points, and no longer. For a single scheduled job, that is usually a few pages. Length is not the goal; the test is whether someone who did not write the job can diagnose and recover it without calling the author.
What if the author has already left?
Reconstruct from what exists: the script, the logs, the scheduler configuration, and the incident history. The failure inventory becomes a set of hypotheses to verify rather than a record of known behavior. Start with the success check, because without it you cannot tell whether the job is working now.
Should the handoff include a rewrite plan?
It can, as a separate section, but the rewrite should not substitute for the failure inventory. A rewrite scheduled for next quarter does not help the on-call engineer next week. Document the current job’s failure modes first, then propose the rewrite as an action item with an owner.
How does this relate to a broader recovery checklist?
The cron job handoff is a narrow instance of a broader problem: knowing what to do when something breaks and the person who knew is unavailable. A recovery checklist for the wider system is a useful companion, and the Recovery Checklist covers that ground. The cron job document should link to it rather than duplicate it.
What is the single most important section?
The success check. Without it, the next person cannot distinguish a quiet job from a broken one, and every other section of the document is harder to use. If time is short, write the success check first.