This note is not a hiring post. It is a triage plan for the first week after the resignation, written as if the person had already left. Because in practice they already have: mentally they are in the next job, and every day that passes the cost of extracting what they know goes up.
If you run a 15–60 person company and your only infrastructure person just handed in notice, you do not need a replacement this week. You need that, within thirty days, the rest of the team can deploy, rotate a key and restore a backup without calling anybody on WhatsApp.
Day 0 — the freeze
The first impulse is to use “while they are still here”: migrate to that new vendor, bump the major Kubernetes version, rewrite the pipeline “properly for once”. It is the most expensive impulse of the thirty days. Every new change is new knowledge that has to be handed over on top of the old knowledge you have not extracted yet.
What you stop the same day:
- Vendor, region or cluster migrations.
- Major version bumps of anything that touches production.
- “While I’m here” refactors: renaming modules, reshuffling repos, “cleaning up” Terraform.
- Hiring somebody “fast” so the leaver can teach them. Two new people at once do not double the handover: they dilute it.
The one thing you start the same day: recording. Every handover session on video, screen shared, stored where the team can find it without asking permission. A Confluence page written from memory at two in the afternoon does not replace watching the person open the console, hesitate and correct themselves.
The Day 0 rule, said out loud in the first meeting: “During the notice period we do not improve the system. We make it transferable.”
The inventory nobody has
Everybody remembers the servers. Nobody remembers the rest. The inventory that matters is not the instance list: it is the list of logins, invoices and rituals that only fit in one person’s head. If you want the map of what the cluster actually does, not what the diagram says, start with the cluster you can explain.
The short list we ask for on day 1, with an owner and a screenshot that somebody else can get in:
- Domain registrar login and the DNS zone.
- Cloud root account (and who holds the 2FA phone).
- Certificate renewal: if it is a cron on somebody’s laptop, that cron is critical debt.
- Paid CI seats, the Jenkins or “temporary” runner that has been there three years, and personal API tokens embedded in pipelines.
- Billing accounts: cloud, CDN, monitoring, the SMS provider for customer 2FA.
- Secrets that are not in the secret manager: CI variables, .env files on a bastion, passwords in a personal password manager.
If an item on that list does not have a second human with verified access by Friday of week 1, that item is the month-3 incident.
Week 1 — credentials before knowledge
The classic handover mistake is to start with architecture. Start with the keys. Most teams discover the outage here, by rotating a key and watching the deploy die, rather than in month 3, when the person no longer picks up the phone.
- Inventory every human identity with console access or an access key.
- Rotate long-lived keys. Federate what you can (OIDC from CI, SSO for humans).
- Prove, on the same day as the rotation, that somebody who is not the leaver can still deploy.
- Remove the leaver from privileged groups only after that proof, not before.
The proof is not “the pipeline is green”. The proof is: another person merges a trivial change, the pipeline uses the new credentials, and production reflects the change. If that fails, you have found the real bus factor. Better now.
Week 2 — one deploy, done by somebody else
The whole week fits in one rule: somebody on the team deploys a real service to production, with the leaver watching and not typing. Not “I do it and you watch”. Not “we share the keyboard”. The leaver talks. The other person types.
If the path from commit to production still does not fit on a whiteboard, this is the week you reduce it to that, you do not redesign it. The long version of that path is in one path to production: one artifact, promotion by digest, a rehearsed rollback.
By the end of week 2 you want three proofs, not a document:
- Somebody other than the leaver has shipped to production with no keyboard help.
- That person knows how to abort or roll back without asking where the button is.
- The session is recorded and that service’s runbook fits on one page.
If by Friday that has not happened, week 3 does not fix the problem: it documents it. For a handover, documenting a path nobody has walked is theatre.
Week 3 — the four runbooks that matter
You do not need the full wiki. You need four procedures somebody on the team can run at three in the morning without inventing. Everything else can be rediscovered; these four cannot, not in time.
- Deploy: from merged commit to production traffic, with the checks that matter and the owner of each gate.
- Rollback: one command, the previous known-good digest, and what a rollback does not fix (migrations, queued messages, flags).
- Restore from backup: where the backup lives, how you verify it is not empty, how long it takes, and who authorises a production restore.
- “The site is down and I do not know why”: the five dashboards, the three log queries, the feature-flag kill switch, and the DNS or CDN vendor number.
Each runbook is written while it is executed, not afterwards. If while writing it you discover a step that only exists in the leaver’s head, that step is the afternoon’s work, not a margin note.
Week 4 — what you deliberately do not fix
The temptation of the last week is to rewrite. Naming the debt you choose to keep is how you stop the panic and the “while we are at it”. You make an explicit list, signed by whoever stays in charge:
- Which services remain single-committer, and why they are not touched this quarter.
- Which infrastructure pieces remain outside code, and the date when that stops being acceptable.
- Which alerts are known noise, and who is allowed to silence them without opening an incident.
- What will not be migrated until the new hire (or a temporary backfill) is settled.
A list of chosen debt is a plan. A list of denied debt is the month-4 incident, when the new hire arrives to an undocumented mess and assumes the silence was quality.
Artifact: a bus-factor audit
Before you negotiate priorities, pull the numbers. Three blocks, copy-paste. Adapt the cloud; the rest works anywhere.
1. Single-committer services
# from a checkout that contains your service repos as subdirs
for d in */; do
[ -d "$d/.git" ] || continue
echo "=== $d ==="
git -C "$d" shortlog -sne --all | head -5
authors=$(git -C "$d" shortlog -sne --all | wc -l)
top=$(git -C "$d" shortlog -sne --all | head -1 | awk '{print $1}')
total=$(git -C "$d" rev-list --count --all 2>/dev/null || echo 0)
if [ "$authors" -le 2 ] && [ "$total" -gt 20 ]; then
echo "BUS FACTOR RISK: ≤2 authors, $total commits, top author ~$top commits"
fi
done
2. Humans with console access and access-key age
# ── AWS ──
aws iam get-account-authorization-details --output json \
| jq -r '
.UserDetailList[]
| select(.UserName | test("(?i)service|bot|ci") | not)
| . as $u
| ($u.AttachedManagedPolicies + ($u.UserPolicyList // [])) as $pols
| ($u.AccessKeys // [])[]?
| [$u.UserName, .AccessKeyId, .Status, .CreateDate]
| @tsv
'
# console users (password last used is a proxy for "still human")
aws iam generate-credential-report >/dev/null
aws iam get-credential-report --output text --query Content \
| base64 -d | cut -d, -f1,4,5,9,11,14
# ── GCP ──
gcloud projects get-iam-policy "$PROJECT_ID" \
--flatten="bindings[].members" \
--filter="bindings.members:user:" \
--format="table(bindings.role, bindings.members)"
# user-managed service-account keys (inspect ages in the output)
listing=$(gcloud iam service-accounts list --format='value(email)')
for sa in $listing; do
gcloud iam service-accounts keys list --iam-account="$sa" \
--format="table(name.basename(), validAfterTime, keyType)" \
--filter="keyType=USER_MANAGED"
done
# ── Azure ──
az ad user list --query "[].{upn:userPrincipalName, enabled:accountEnabled}" -o table
az ad sp list --all --query "[?passwordCredentials[0]!=null].{
displayName:displayName,
appId:appId,
keyCount:length(passwordCredentials)
}" -o table
3. Secrets with no rotation date
# ── AWS Secrets Manager ──
aws secretsmanager list-secrets --query \
"SecretList[?LastRotatedDate==null].[Name,LastChangedDate,LastAccessedDate]" \
--output table
aws secretsmanager list-secrets --query \
"SecretList[?LastRotatedDate!=null].[Name,LastRotatedDate]" \
--output table
# ── GCP Secret Manager ──
gcloud secrets list --format="table(name, createTime, replication.automatic)"
# ── GitHub Actions org secrets (needs admin + gh) ──
gh api orgs/$ORG/actions/secrets --jq \
'.secrets[] | [.name, .updated_at, .visibility] | @tsv'
# personal tokens still living in workflow files: search, then rotate
git grep -nE 'ghp_|gho_|github_pat_|AKIA[0-9A-Z]{16}' -- '*.yml' '*.yaml' || true
What you want is not a pretty report. It is three lists: services only one person touches, human identities with old keys, and secrets that have never been rotated. Those three lists are the order of week 1.
Where this breaks in practice
- The exit interview that becomes a blame session. The leaver stops sharing the day they feel three years of work are on trial. Keep the technical handover separate from the HR conversation.
- “Still available on WhatsApp”. That is not a plan. It is debt with compound interest and no SLA. If you need ad-hoc retention, contract it in writing, with hours and a price. If not, assume the phone does not exist after the last day.
- The replacement hire who arrives in month 4 to an undocumented mess. You spent the notice period making it “all clear” in the leaver’s head, not in proofs executed by whoever stays. Month 4 then rediscovers the same thing, more expensively.
- Freezing too little: a “quick fix” in week 3 that only the leaver understands. If it does not fit in the one-page runbook, wait.
What remains when the notice period ends
Success for these thirty days is not a hired replacement or a new diagram. It is drier: two people can deploy, one critical key has been rotated with proof, four runbooks exist because they were executed, and the debt you did not touch has a name and an owner.
Hire afterwards. Or bring in backfill. But do not confuse the job post with the handover: one buys future time, the other buys the time you still have.
Send us the list of things only one person could do. We only rank three: whether somebody else can still deploy, whether a login or a 2FA phone leaves with them, and whether you can restore a backup without them. The rest: names, wikis, noisy alerts, waits. Within 24h you get those three back, and what the 30-day version of fixing them looks like.