Backups & restore
ADMINISTRATORSchedule
| When | What |
|---|---|
| 03:00 UTC daily | Cron triggers wrangler d1 export pms-db → R2 bucket pms at backups/pms-db-YYYY-MM-DD.sql |
| 03:00 UTC daily | Vectorize export → backups/vec-YYYY-MM-DD.ndjson |
| 04:00 UTC daily | Retention sweep — deletes anything older than 30 days |
Listing
wrangler r2 object list pms --prefix backups/ | headRestore
Destructive
Restore overwrites the live DB with the snapshot. Schedule a maintenance window, post ai-status notice, verify the snapshot date.
# 1. Schedule maintenance
# 2. Flip MAINTENANCE_MODE in App.tsx so users see a banner
# 3. Take a fresh export of the current state (so you can roll forward)
wrangler d1 export pms-db --remote --output=pre-restore-$(date +%F).sql
# 4. Pull the target snapshot from R2
wrangler r2 object get pms backups/pms-db-2026-04-27.sql > snapshot.sql
# 5. Inspect
head -200 snapshot.sql
grep -c "INSERT INTO" snapshot.sql
# 6. Apply
wrangler d1 execute pms-db --remote --file=snapshot.sql
# 7. Verify
curl https://pmsplanner.com/api/health | jq .
# 8. Audit-log the restore
# (handled automatically by /api/admin/backups/restore — see Worker code)
# 9. Lift MAINTENANCE_MODEWhat a backup contains
The pms-db-*.sql is a full schema + data dump from wrangler d1 export. The Vectorize NDJSON contains all embedded vectors keyed by id. Re-applying both gives you a byte-for-byte equivalent system at the snapshot moment.
rag-corpus is a separate D1 with its own wrangler d1 export rag-corpus. The cron exports it as backups/rag-corpus-YYYY-MM-DD.sql (verify in your wrangler.jsonc cron handler).
R2 image backups
Since v2.12.15, FLUX-generated component images are written to R2 (not D1) via /api/component-images/:key proxy. They are part of the R2 bucket and survive D1 restores intact — no separate backup needed beyond R2 lifecycle policy.