Backup and restore
Duckbill™ backs up application-owned state. Providers can re-fetch message bodies. Rules, corrections, classifications, attention, audit, and sync metadata cannot (MAIL-46 / MAIL-56 / ADR 0026).
Objectives
| Objective | MVP target |
|---|---|
| RPO | ≤ 24 hours for application-owned persistent state |
| RTO | ≤ 4 hours for a recoverable application/database failure |
These are release targets, not promises about Microsoft or other providers.
What is backed up
- Feature-flag configuration (names and booleans only)
application_rulesapplication_correctionsandhuman_corrections(MAIL-54)classificationsconversation_states(attention)audit_eventssync_checkpoints(status and cursor presence, not token ciphertext)
What is skipped
provider_tokensand OAuth leftovers- Short-lived body caches
- Regenerable search indexes
- Mail body bytes (re-fetch from the provider after restore)
Losing encrypted tokens means reconnecting the mailbox. That is preferred to copying secrets into backup files.
Recovery mode
After a restore:
- Enter recovery mode (
ops_recovery_modeplus aGLOBALautomation pause). - Provider mutations stay paused.
- Run reconciliation and validate checkpoints.
- Confirm rules and classifications.
- An operator clears recovery before write-back resumes.
assertMutationsAllowed fails closed while recovery is active.
How to run a backup
npx tsx scripts/backup-restore.ts export --out /tmp/duckbill-app-state.json
Requires DATABASE_URL. The JSON file must be stored as a secret artifact, not committed.
How to restore (runbook)
- Provision a disposable or recovered Postgres and apply migrations (
npm run db:migrate). - Restore users, connected accounts, and mail identity rows from the platform backup or reconnect.
npx tsx scripts/backup-restore.ts restore --in /tmp/duckbill-app-state.json- Confirm recovery mode is active and mutations are paused.
- Run reconciliation for each account.
- Clear recovery only after attention, rules, and audit match the checklist.
Restore rehearsal
CI exercises the path on ephemeral PGlite with fixtures/ops/backup-restore-sample.json. The recorded checklist is fixtures/ops/restore-rehearsal-checklist.json. That fixture is synthetic. Production mailbox content is forbidden.
Related
Host deploy order and recovery-mode gates are in deploy and operate. Formal NFR restore evidence is owned by MAIL-109.
