Skip to content

AI-Powered Disaster Recovery

Disaster recovery with AI coding agents covers two blast radii: a change an agent shipped, undone through checkpoints, revertable commits, feature flags and targeted reverts; and the infrastructure underneath, restored through point-in-time-recovery runbooks, backups and rehearsed failover. Both depend on recovery objectives stated in advance, drills that measure them, and a human at every irreversible step.

This guide is for the developer who carries the pager and the tech lead who owns a service’s recovery plan. The scenario it prepares you for: an agent refactors the auth module across 47 files, tests pass, you merge, and two hours later the admin API stops validating session tokens while three other PRs have landed on top. A month later the primary region goes dark mid-deploy, and the Postgres runbook points at a host that was decommissioned in the spring.

What you’ll walk away with from this disaster-recovery playbook

Section titled “What you’ll walk away with from this disaster-recovery playbook”
  • A recovery-objective table (RTO and RPO per tier) that turns every later artifact into something you can test
  • Per-tool settings and two prompts that keep an agent’s large change revertable one commit at a time
  • A revert-first procedure for a merged agent change that is hurting production, with the prompt that drives it
  • A prompt that generates a Postgres point-in-time-recovery (PITR) runbook from your real pgBackRest config, and a scheduled, read-only agent job that fails CI when the runbook drifts from that config
  • A Chaos Mesh failover drill with pass and fail criteria measured against your RTO and RPO, and a named person who signs off
  • A human-gated failover prompt, a blameless post-mortem prompt, and the failure modes that silently break recovery plans

Name the blast radius before you pick a tool. The two kinds need different mechanics, but the same discipline.

An agent’s changeThe infrastructure
Blast radiusA commit, a PR or a deployA database, a cluster or a region, and everything on top of it
Recovery mechanismCheckpoint, git revert, feature-flag flip, minimal hotfixRestore from backup, replica promotion, regional failover
Measured againstTime from alert to rollbackRTO (time to restore service) and RPO (data you can afford to lose)
What decides successWhether the change was small enough to undo cleanlyWhether the procedure was rehearsed against the real topology
Who approves the irreversible stepThe on-call engineer who owns the serviceThe incident commander

The agent drafts, checks and explains at both scales. A person approves every step that cannot be undone: a force-push, a data restore, a replica promotion, a DNS cutover.

Set recovery objectives before you generate anything

Section titled “Set recovery objectives before you generate anything”

Every artifact below depends on two numbers per service tier. A runbook that targets “fast recovery” cannot fail a drill; one that targets “RTO 15 minutes, RPO 5 minutes for payments” can. Start from this template and replace the values with the ones your business signs off:

TierExample servicesRTORPOBackup approach
Criticalauth, payments15 min0–5 minStreaming replica plus continuous WAL archiving
Highcore API1 hour5 minWAL archiving plus frequent base backups
Mediumsecondary features4 hours1 hourHourly snapshots
Lowinternal tooling24 hours24 hoursDaily backups

Commit the table next to your runbooks, for example as ops/recovery-objectives.md, so every prompt below can point the agent at it instead of restating numbers.

Make an agent’s change recoverable before it merges

Section titled “Make an agent’s change recoverable before it merges”

The cheapest recovery is the one you set up before the agent starts. Each tool keeps a local undo for agent edits, but none of them replaces Git: a checkpoint lives on one machine, misses some kinds of change, and never covers what already merged.

Claude Code checkpoints its file edits before each prompt you send. Run /rewind, or press Esc twice with an empty prompt, and choose to restore the code, the conversation or both. Checkpoints do not track files changed by Bash commands such as rm or a migration script, so commit before you let the agent run anything destructive. Old checkpoints are cleaned up automatically, so do not treat them as an archive.

Put the durable rules in CLAUDE.md. From v2.1.277 on the latest channel, Claude Code also reads AGENTS.md when a project has no CLAUDE.md; on Bedrock, Google Cloud, Foundry and LLM gateways that needs v2.1.281. The rule text is in the block below this tab set.

The safety rules themselves are identical across the three tools:

## Change safety
- Work on a branch named agent/<task>. Never commit to main. Never force-push.
- Before a change that touches more than 10 files, list the files and wait for approval.
- Commit after each step that passes `npm test` and `npm run typecheck`. One logical step per commit.
- Never delete a file, edit a migration that has run, or change *.config.*, .env*, Dockerfile
or infra/ without showing the diff and waiting for approval.
- If a test fails after a step, revert that step's commit and report why. Do not fix forward.

Two habits make the difference between a two-minute revert and an afternoon of untangling: commit in steps that each pass the tests, and pin down current behaviour in tests before the rewrite starts.

The mutation step is how you know the tests can fail; a behaviour-capture suite that stays green when you break the code protects nothing. The full technique is in characterization tests.

Roll back an agent’s change that already shipped

Section titled “Roll back an agent’s change that already shipped”

Speed beats elegance once a merged change is hurting production. Work in this order and stop at the first step that restores service:

  1. Flip the flag. If the change shipped behind a feature flag, turn it off. This is why agent-written changes should ship behind flags and canaries; the setup is in progressive delivery.

  2. Revert the merge. Revert the merge commit on main and let CI deploy it:

    Terminal window
    # Terminal: find the merge commit for the PR, then revert it (keep the main-line parent)
    git log --merges --oneline -20
    git revert -m 1 MERGE_SHA

    MERGE_SHA is the merge commit from the log. If the PR was squash-merged, find it with git log --oneline and run git revert SHA without -m 1. If later PRs depend on the agent’s code and the revert conflicts, skip to step 3 rather than untangling mid-incident.

  3. Ship a minimal hotfix. Restore the behaviour that broke, and change nothing else; open the proper fix as a normal PR after the incident.

  4. Check for deleted files. An agent’s refactor can delete a file whose absence nobody notices until the code path runs. List what the PR removed with git diff --name-only --diff-filter=D MERGE_SHA^1 MERGE_SHA and restore a file with git checkout MERGE_SHA^ -- PATH.

The regression test in step 5 is the verification: it fails on the broken build and passes on the fix, so the reviewer checks one test and one small diff instead of rereading the refactor.

Recover data an agent’s change corrupted

Section titled “Recover data an agent’s change corrupted”

This is where the two blast radii meet: the code fix is a revert, but the data fix is a restore.

  1. Stop writes from the bad code. Deploy the rollback or flip the flag first. Do not fix forward while bad writes continue.

  2. Measure the damage with read-only queries. Ask the agent for SELECT statements that find rows written or updated during the incident window, and run them yourself against a read replica. Record the row counts before you change anything.

  3. Restore into a side database. Use the PITR runbook below to restore to a timestamp just before the bad deploy, into a separate instance, never over the live primary.

  4. Repair with a reviewed script. Have the agent write the repair script that copies correct values from the side database, run it first on a copy, compare row counts and checksums against step 2, and get a second person to approve it before it runs on production.

  5. Close the gap. Add a database constraint or a validation test that would have rejected the bad writes, and record the failure class (see the failure taxonomy).

Generate a Postgres PITR runbook your on-call can follow

Section titled “Generate a Postgres PITR runbook your on-call can follow”

A point-in-time-recovery runbook is the recovery artifact on-call engineers reach for first, so write one they can follow half asleep. The pattern that works is continuous WAL archiving plus an external backup tool such as pgBackRest or WAL-G. A restore sets a recovery_target_time and needs an unbroken WAL chain from the base backup to that target. Have the agent write the runbook against your real configuration, not a template:

The last instruction exists because the two things an agent most often gets wrong here are invented pgBackRest options and a skipped WAL-gap check. Run pgbackrest help restore and check each listed option before the runbook is merged. The core of a correct runbook looks like this:

Terminal window
# On the recovery host, as the postgres user
pgbackrest --stanza=prod-main info # backups and the WAL range each one needs
pgbackrest --stanza=prod-main verify # checks backup and WAL archive integrity
pgbackrest --stanza=prod-main --type=time \
"--target=2026-09-25 14:02:00+00" --target-action=promote restore

Keep the runbook true with a scheduled drift check

Section titled “Keep the runbook true with a scheduled drift check”

A runbook rots the day someone renames a stanza or moves a host. Run a read-only agent against it on a schedule, from the default branch, and fail the job when it drifts from the config.

Terminal window
# Scheduled CI job on the default branch; ANTHROPIC_API_KEY comes from the secret store
claude -p "Read infra/pgbackrest.conf and ops/runbooks/pitr.md. Check that every stanza,
host, bucket and path in the runbook exists in the config. Print one line per mismatch.
End with DRIFT if there is at least one mismatch, otherwise CLEAN." \
--allowedTools "Read,Grep,Glob" --permission-mode dontAsk > drift.txt
tail -n 1 drift.txt | tr -d '*[:space:]' | grep -qx CLEAN

--permission-mode dontAsk denies every tool that is not on the allow list, so the job can only read. The last line turns the verdict into the job’s exit code; tr -d strips Markdown such as **CLEAN** that the model may wrap around the word, so formatting cannot fail the job.

Run the job with a token that can read the repository and nothing else (permissions: contents: read in GitHub Actions, and persist-credentials: false on checkout). The details of running agents safely in CI are in headless agents in CI.

Audit real backup settings instead of guessing them

Section titled “Audit real backup settings instead of guessing them”

A generated backup policy is only plausible. Connected to your cloud account through an MCP server with a read-only identity, the agent can read the actual bucket lifecycle rules, snapshot schedules and replica regions, and tell you where the RPO gap is. The AWS server is registered the same way in each tool; this example uses a profile bound to a read-only IAM role, and adds the proxy’s --read-only flag, which hides tools that may need write permissions, as a second layer on top of the role. The endpoint stays us-east-1; the region you query is passed as AWS_REGION metadata (without --metadata, it comes from the profile). In Claude Code or Codex, run /mcp afterwards; in Cursor, open the MCP settings. Confirm the tools you need are still listed. The managed AWS MCP Server is labelled preview in the awslabs README (checked 2026-09-26); in Claude Code you can also install it as the aws-core plugin from claude-plugins-official:

Terminal window
claude mcp add aws-mcp -- uvx mcp-proxy-for-aws-cli@latest \
https://aws-mcp.us-east-1.api.aws/mcp --profile agent-readonly --metadata AWS_REGION=eu-west-1 --read-only

Azure, Google Cloud and the other providers, with their read-only settings, are covered in cloud platform MCP servers; Kubernetes and Terraform are in infrastructure MCP servers.

For Kubernetes workloads, Velero backs up cluster resources and persistent volumes. Ask for a Schedule covering the payments and auth namespaces whose cron interval meets the tier’s RPO, with a TTL that meets your retention policy, then prove it by restoring into a scratch namespace with velero restore create --from-backup BACKUP_NAME --namespace-mappings payments:payments-drill. A backup you have never restored is not a backup.

Prove failover works with a scheduled chaos drill

Section titled “Prove failover works with a scheduled chaos drill”

An untested recovery plan is a hypothesis. A scheduled Chaos Mesh experiment tests failover continuously: the Schedule resource (apiVersion: chaos-mesh.org/v1alpha1) runs a PodChaos pod-kill on a cron.

The manifest is the easy half. The pass and fail definition is what turns killing pods into evidence.

  1. Run the drill in a staging cluster that mirrors production topology, never against customer traffic.

  2. Let drill-report.sh record kill time, promotion time and first successful write automatically; nobody reads logs by hand.

  3. Treat a FAIL as a P2 ticket with an owner, not a curiosity.

  4. Have the service’s tech lead sign off each month’s drill results in the ticket. That signature, not a green backup dashboard, is your evidence that the RTO and RPO hold.

  5. Feed each failed drill into the post-mortem prompt at the end of this guide.

Run the live failover with a human at every irreversible step

Section titled “Run the live failover with a human at every irreversible step”

Mid-incident, use the agent to generate and check the next action, never to execute irreversible commands from free text. Keep the session read-only and let a person run each command. The wider incident loop (paging, triage, status updates) is in incident response.

The same discipline covers ransomware: the agent can read the backup catalogue and the file-modification timeline to find the last backup that finished before the first encryption event, and draft network-isolation rules, while a person runs the restore.

What breaks disaster recovery plans, and how do you recover?

Section titled “What breaks disaster recovery plans, and how do you recover?”
  • A WAL gap strands the restore. A lifecycle rule or a failing archive_command removed segments. Recovery: restore to the latest target the remaining chain supports, report the real data loss, and add verify plus a lifecycle check to the drift job.
  • Replication lag exceeds the RPO at the worst moment. The write spike that precedes an outage leaves the standby minutes behind. Recovery: alert on lag against the RPO number, and make the failover checklist compare lag before promotion; see monitoring and observability.
  • Split-brain after failover. The old primary still accepts writes after the standby is promoted. Recovery: fence the old primary first, snapshot it, export the rows it accepted after the promotion time (diff against the new primary) and replay them after review, then rebuild it as a standby with pg_rewind or a fresh base backup; keep “stop writes” as step one of every failover checklist.
  • The drill passes and the real failover fails. Staging has three nodes and production has 30. Recovery: mirror production topology in the drill cluster, and rotate the injected failure (pod kill, network partition, disk full).
  • The agent invents a flag or a CRD field. The runbook or manifest will not run. Recovery: the prompts above make the agent list every option with its source; check that list against --help or the CRD types before merging.
  • A revert conflicts because later PRs build on the agent’s code. Recovery: ship the minimal hotfix instead of untangling commits during the incident, then schedule the proper fix. Revertable commits (above) make this rarer.
  • The checkpoint you need is not there. The change came from a shell command that checkpoints do not track, or the snapshots were already swept. Recovery: Git is the durable record; commit per step so there is always a commit to return to.

Turn the incident into a post-mortem and a regression test

Section titled “Turn the incident into a post-mortem and a regression test”

The incident is not closed until the lesson is in the repository: a post-mortem, a regression test, and a changed runbook or rule. Feed the agent the real artifacts, not your memory of them.

Store the post-mortem next to the runbook it should change, so the next drill tests against the lesson from the last incident. For incidents caused by an agent’s change, tag the failure class and follow the organisational process in agent incidents.