Skip to content

Backup & Restore Runbook

Executive Overview — all summaries for decision-makers.

Overview

ComponentBackup methodTarget frequencyStorage location
PostgreSQLRender PITR (Pro plan)ContinuousRender Frankfurt
PostgreSQLpg_dump directory formatMonthlyCloudflare R2 (MQA)
R2 mediaR2 versioning / replicationEnable on migrationCloudflare
Render uploads (/uploads)⚠️ EphemeralR2 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.gz

Upload 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.

  1. Announce maintenance window
  2. Scale down Render backend or enable maintenance mode
  3. Run restore → DATABASE-RESTORE
  4. Sync migrations:
bash
cd backend
npx prisma migrate deploy
# On conflicts (schema already in dump):
npx prisma migrate resolve --applied <migration_name>
  1. Smoke tests → DEPLOYMENT-CHECKLIST
  2. Redeploy backend

Render Postgres PITR

Render Dashboard → mqa-postgresBackups → Point-in-Time Recovery.

Use for accidental DELETE, not for schema migration errors.

Restore Test (quarterly)

StepExpected result
Load backup from R2Archive intact
Restore to staging DBNo errors
Check User count> 0
OAuth login on stagingWorks
DocumentDate + owner in OPS-ROADMAP

Emergency Contacts

RoleAction
Lead DeveloperRun restore, deploy
MQA ITDNS, Azure, Cloudflare
Render SupportDB PITR, platform outage

Change History

DateEvent
2026-08-03Prod DB restored from June 2026 dump; runbook created