| Tier | RPO (data loss) | RTO (downtime) | Backup mechanism | Retention |
|---|---|---|---|---|
| Trial | ≤ 24h | Best-effort | RDS PITR only | 7 days |
| Starter | ≤ 24h | ≤ 8h | RDS PITR + tenant export on-demand | 7 days |
| Growth | ≤ 4h | ≤ 4h | RDS PITR + daily S3 pgdump | 30 days |
| IVIP Visibility | ≤ 4h | ≤ 4h | Same as Growth | 30 days |
| Enterprise | ≤ 1h | ≤ 1h | RDS PITR + S3 pgdump + cross-region replica | 90 days (30d Standard + 60d IA) |
All backups land under s3://{BACKUPS_BUCKET}/ with per-prefix lifecycle policies (see infra/terraform/backups.tf):
| Prefix | Purpose | Lifecycle |
|---|---|---|
exports/ | Per-tenant GDPR Art. 20 export (on-demand, customer-pull) | 7 days |
pgdump/ | Daily logical pg_dump of full DB | 90 days (Standard-IA after 30d) |
vault/ | Vault snapshots (VACUUM INTO + decrypt-verify) | 90 days (Standard-IA after 30d) |
tier-backups/business/ | Per-tenant daily backup for Growth/IVIP customers | 30 days |
tier-backups/enterprise/ | Per-tenant daily backup for Enterprise customers | 90 days (Standard-IA after 30d) |
Customer can self-serve via the tenant settings page. Or vendor-initiated:
Includes audit_event (customer's right to their full audit trail). Excluded only from hard-delete tenant flow per CLAUDE.md durable rule #1.
Per CLAUDE.md SLA invariants: backup that isn't tested = backup that doesn't work. Schedule via .github/workflows/rds-restore-drill.yml:
db.t3.medium ephemeral RDS from latest snapshot → run validation script → tear downFor 99.99% SLA customers — workflow lives in .github/workflows/rds-cross-region-copy.yml:
Per CLAUDE.md security rule #1 + migration 0139: audit_event is DB-immutable via PostgreSQL BEFORE UPDATE OR DELETE trigger. ORM code that mutates an audit row → request crashes.
This invariant survives restores because the trigger is part of the schema. After any restore:
If the trigger is missing post-restore, re-apply via alembic upgrade 0139 — it's idempotent.
Per CLAUDE.md durable rule #2: typed-confirm + OFFBOARDING-gated. Flow:
OFFBOARDING (admin action via UI)POST /platform/tenants/{id}/delete with confirm={tenant_id} exactaudit_event rows are preserved under GDPR Art. 17(3)(b) — compliance retention ground