Durability, backup and recovery
What can be recovered and what cannot: D1 point-in-time recovery over a 30-day window, per-file version history, deployment rollback, and the RPO and RTO you can actually claim — plus a restore drill to run before you need one.
Enterprise reviews ask two questions here: what can you get back, and how long does it take. This page answers both precisely, including where the answer is "you can't".
What is recoverable
| Asset | Mechanism | Window | Granularity |
|---|---|---|---|
| D1 database | Time Travel point-in-time recovery | 30 days | Any moment — timestamp or bookmark |
| Application source | Version control (every AI turn and edit is a commit) | Full history | Per commit, per file |
| Individual files | Per-file version history | Full history | Per file version |
| A running environment | Deploy an earlier commit | Full history | Per deployment |
| Durable Object storage | — | None | Durable, but not rewindable |
| KV values | — | None | — |
| R2 objects | — | None by default | Immutable keys; a new key never overwrites an old one |
The shape of that table is the design guidance: D1 is the only store you can rewind. State whose loss would be unacceptable belongs there, or must be mirrored there.
Point-in-time recovery for D1
There is no backup job to schedule and no snapshot to remember. Recovery is continuous over a rolling 30-day window:
sf d1 history # available bookmarks
sf d1 restore --minutes-ago 30 --yes # rewind the database
That covers the failure that actually happens — a bad UPDATE, a migration that did more than intended, a script run against the wrong environment — with recovery to the moment before it, not to last night.
Three properties to be precise about with an auditor:
- RPO is effectively zero within the window. You recover to a point in time, so committed writes up to the incident are recoverable. This is materially stronger than a nightly-snapshot posture, where the RPO is "up to 24 hours".
- The window is 30 days and is not configurable. Anything requiring longer retention needs a periodic export into your own long-term storage — a scheduled job writing to R2 or an external warehouse. If your policy requires seven-year retention, that is an application-level obligation, not something the platform does for you.
- A restore is destructive. It rewinds the whole database, discarding everything after the chosen point. Check
sf d1 historyfirst, and never let a first-ever restore be the one you perform during an incident.
Recovery time objectives
Measured against the commands that perform them, not aspirational:
| Scenario | Action | RTO |
|---|---|---|
| Bad deploy — code is wrong | Deploy an earlier commit | ~1 minute |
| Bad data write — rows corrupted | sf d1 restore to a bookmark |
Minutes |
| Bad migration | Restore, then fix the migration forward | Minutes |
| Accidental file deletion | Restore the file version, or roll back the commit | Seconds to minutes |
| A store is degraded upstream | Serve degraded (cache + static) until it recovers | Depends on the provider |
| Durable Object state lost or wrong | No restore path — rebuild from D1 if mirrored | Unbounded if not mirrored |
Two of these deserve emphasis. A code rollback is a normal deploy, not an escalation — sf deploy --env production --commit @1 pins the environment to a known-good commit without touching the branch. And the last row is the one to design away: if a Durable Object holds state whose loss would matter, mirror it to D1 as it changes.
How writes become durable
Cloudflare's documentation describes D1 writes as needing to be "durably persisted across several locations" before acknowledgement. The consequence for your application is the ordering above: when a write returns successfully, it is committed — replication to read replicas happens afterwards, which is exactly why the session bookmark exists. See Consistency and correctness.
Source and configuration recovery
Application code is under version control where every AI turn and editor change is a commit, which has an audit property worth naming: there is no path by which a change reaches the app without a commit recording who or what made it.
sf vcs log # who changed what, when
sf vcs diff <path> # what changed
sf vcs rollback @3 --confirm # revert the app; creates a NEW commit, so it's reversible
sf files versions <path> # per-file version history
A rollback creates a new commit rather than rewriting history, so the recovery action is itself auditable and itself reversible.
The restore drill
Run this before you need it. It takes about ten minutes and is the only way to know your RTO is real:
# 1. In a NON-PRODUCTION environment, note a known-good point
sf d1 history --env staging
# 2. Cause damage on purpose
sf d1 execute --env staging "UPDATE orders SET status = 'cancelled'"
# 3. Confirm the damage
sf d1 select --env staging "SELECT status, COUNT(*) FROM orders GROUP BY status"
# 4. Recover
sf d1 restore --env staging --minutes-ago 10 --yes
# 5. Verify
sf d1 select --env staging "SELECT status, COUNT(*) FROM orders GROUP BY status"
What the drill teaches that a document cannot: how long it actually takes, what the output looks like under pressure, and — most usefully — whether anything important lives outside D1. If step 5 shows the database correct but the application still broken, you have found state in a Durable Object or KV that no restore will bring back. Better to learn that on a Tuesday afternoon in staging.
Do the same for code:
sf deploy --env staging --commit @3 # roll back
sf deploy --env staging # roll forward
Long-term retention
Because the D1 window is 30 days, a longer retention obligation is your application's to meet. The conventional pattern is a scheduled job exporting to durable storage you control:
- A routine or scheduled job runs nightly.
- It writes a dated export to R2 or an external warehouse.
- Immutable asset keys mean an export can never be silently overwritten.
Design this deliberately if you have a regulatory retention period — and tell us the requirement early, because it changes what you build.
Next
- Failure domains and resilience — staying useful while something is degraded.
- Change management and rollback — the deploy side of recovery.
- SLAs, limits and quotas — commitments and every published limit.
Frequently asked questions
How far back can we restore the database?
30 days. D1's Time Travel gives point-in-time recovery to any moment in that window, addressed by timestamp or bookmark — there is no backup schedule to configure and no snapshot to remember to take.
What is the RPO?
Effectively zero for D1: recovery is to a point in time, not to the last nightly snapshot, so committed writes up to the moment of the incident are recoverable. Durable Object state and KV have no point-in-time recovery — treat their RPO as unbounded.
What is the RTO?
A database restore is a single command that completes in minutes. A code rollback is one deploy of an earlier commit, on the order of a minute. Neither requires a support ticket.
What is NOT backed up?
Durable Object storage, KV values, and R2 objects have no point-in-time recovery. Anything you would want to rewind belongs in D1, or must be mirrored there.
Is a restore itself risky?
Yes — it is a destructive operation that discards everything after the chosen point. Check the available bookmarks first, and rehearse on a non-production environment. That rehearsal is the drill described on this page.