Backup & Restore Runbook
Executive Overview — all summaries for decision-makers.
Overview
| Component | Backup method | Target frequency | Storage location |
|---|---|---|---|
| PostgreSQL | Render PITR (Pro plan) | Continuous | Render Frankfurt |
| PostgreSQL | pg_dump directory format | Monthly | Cloudflare R2 (MQA) |
| R2 media | R2 versioning / replication | Enable on migration | Cloudflare |
Render uploads (/uploads) | ⚠️ Ephemeral | — | R2 migration planned |
Automated Backup (Script)
bash
# Prerequisite: DATABASE_URL (external URL with sslmode=require)
export DATABASE_URL='postgresql://...'
./backend/scripts/backup-production-db.sh
# Output: ./backups/mqa_governance_YYYY-MM-DD_HHMM.dir.tar.gzUpload archive to R2 (manual or cron):
bash
# Example with rclone (after configuring MQA R2 remote)
rclone copy backups/ mqa-r2:backups/postgres/Restore (Production)
Caution: Overwrites existing DB objects.
- Announce maintenance window
- Scale down Render backend or enable maintenance mode
- Run restore → DATABASE-RESTORE
- Sync migrations:
bash
cd backend
npx prisma migrate deploy
# On conflicts (schema already in dump):
npx prisma migrate resolve --applied <migration_name>- Smoke tests → DEPLOYMENT-CHECKLIST
- Redeploy backend
Render Postgres PITR
Render Dashboard → mqa-postgres → Backups → Point-in-Time Recovery.
Use for accidental DELETE, not for schema migration errors.
Restore Test (quarterly)
| Step | Expected result |
|---|---|
| Load backup from R2 | Archive intact |
| Restore to staging DB | No errors |
Check User count | > 0 |
| OAuth login on staging | Works |
| Document | Date + owner in OPS-ROADMAP |
Emergency Contacts
| Role | Action |
|---|---|
| Lead Developer | Run restore, deploy |
| MQA IT | DNS, Azure, Cloudflare |
| Render Support | DB PITR, platform outage |
Change History
| Date | Event |
|---|---|
| 2026-08-03 | Prod DB restored from June 2026 dump; runbook created |