PostgreSQL guide
How to test a PostgreSQL backup restore (and automate it)
Testing a restore means actually recovering the backup somewhere safe and checking the result. This guide covers how to set up an isolated target, what to check, how to schedule it, and what record to keep, so the test is repeatable and worth showing to an auditor.
What a restore test has to prove
- The backup restores without errors.
- The restored data is correct: the right database, complete and recent.
- Recovery fits inside your time objective, so you record how long it took.
- The test is repeatable, so next month's result is comparable to this month's.
Set up an isolated target
Never restore a test into production, and do not reuse a long-lived staging database that other people depend on. Use a throwaway server, and match the PostgreSQL major version you run in production. A container is the quickest way:
docker run --rm -d --name pgtest -e POSTGRES_PASSWORD=test -p 55432:5432 postgres:16
pg_restore -h localhost -p 55432 -U postgres -d postgres --exit-on-error --no-owner backup.dump
docker stop pgtestWith a managed provider, restoring a snapshot or a point in time normally creates a new instance. Run your checks against that new instance, then delete it.
Write the checks down
Decide the checks once, in a file under version control, so the test does not depend on someone remembering them.
- Row counts for your most important tables, within an expected range.
- Key tables and columns exist, so schema drift is caught.
- Critical columns contain no nulls.
- The newest row is recent, so a stale backup is caught.
- On PostgreSQL 14 and later, pg_amcheck passes on the restored database.
Run it on a schedule
A test you run by hand when you remember is not a control. Run it weekly at minimum, for example:
0 4 * * 0 /opt/verify-backup.sh /backups/latest.dump >> /var/log/backup-verify.log 2>&1Alert in two cases: the test fails, and the test did not run. The second is the one people forget, and it is how a broken scheduler stays broken for months. A heartbeat or dead-man's-switch check handles it.
Keep a record
For each run, keep the date, which backup was restored, how long the restore took, which checks ran and their results. For SOC 2, ISO 27001 or a cyber-insurance renewal, this dated record is the evidence. Store it somewhere that is not the system being tested, and make it hard to edit after the fact.
Or let it run for you
Dokaz does this for PostgreSQL: each drill restores your backup into a single-use sandbox on an isolated network, runs assertions on the restored data, and produces a signed Proof-of-Recovery report that anyone can verify offline with no Dokaz software. It never connects to your production database.
Prove your backups restore, automatically
Dokaz restore-tests your PostgreSQL backups on a schedule and hands you signed, independently verifiable evidence. Run the sample drill with no card.