Skip to content

Restore from backup

WhatHowRetention
Prod PostgresCloud SQL automated backups + PITR (WAL archiving)35 days
Audit chain snapshotsDaily dump to Cloud Storage bucket tappass-audit-archive7 years
Secret ManagerVersion history (disabled ≠ deleted)Indefinite
Terraform stateVersioned GCS bucketIndefinite

If you need to roll the DB back to a specific moment:

Terminal window
# List backups
gcloud sql backups list --instance=tappass-prod-pg
# Restore to a new instance
gcloud sql instances clone tappass-prod-pg tappass-restore-$(date +%s) \
--point-in-time='2026-04-18T12:00:00Z'

Never restore over the prod instance. Always clone to a new instance, verify, then swap.

  1. Bring the clone up and run integrity checks (see below)
  2. Update Cloud Run connection string to point at the clone
  3. Roll the prod revision
  4. Verify /audit/integrity still reports intact
  5. Snapshot the previous prod instance before deleting it
-- 1. Hash chain integrity
SELECT audit_id, prev_hash, current_hash
FROM audit_events
WHERE current_hash != encode(sha256(... || prev_hash || ...), 'hex')
LIMIT 10;
-- expect 0 rows
-- 2. No gaps in the chain
SELECT COUNT(*) FROM audit_events
WHERE prev_hash IS NOT NULL
AND prev_hash NOT IN (SELECT current_hash FROM audit_events);
-- expect 0
-- 3. Latest event timestamp
SELECT MAX(ts) FROM audit_events;

If PITR isn’t enough and you need to re-ingest from cold storage:

Terminal window
gsutil cp gs://tappass-audit-archive/2026-04-17.jsonl.zst .
zstd -d 2026-04-17.jsonl.zst
# feed into the replay tool
python -m tappass.tools.replay_audit --input 2026-04-17.jsonl

The replay tool re-computes hashes, re-signs with the current key, and inserts in order. Customers see a re-issued audit_replayed event with a reference to the original audit_id.

  • Customer-visible outage of /v1/chat/completions > 5 min
  • Any suspicion of data loss
  • Any break in the audit chain integrity check — compliance event, must be disclosed to affected customers

See Incident response for the flow.