Postgres PITR
Restore PostgreSQL to a specific point in time using pgBackRest.
Use this when you need to roll the database back to a specific moment — typically after a bad migration, an accidental destructive query, or data corruption you can date.
Pre-flight
Know the target time (ISO-8601, e.g.
'2026-04-26 14:00:00 IST') and the time zone.Know whether you want PITR (a specific moment) or just the latest backup set.
Have the
pgbackrest.passpassphrase from your keystore.
Step 1 — Dry-run
Confirms the orchestrator can find the right backup and constructs the right command:
# Latest (no PITR)
./openg2p-backup.sh restore \
--config backup-config.yaml \
--component pg \
--dry-run
# Point-in-time
./openg2p-backup.sh restore \
--config backup-config.yaml \
--component pg \
--point-in-time '2026-04-26 14:00:00' \
--dry-runReads the options, prints the pgBackRest command, exits without touching anything.
Step 2 — Staged restore
Latest backup (full rebuild / “give me the newest set”):
Runs pgbackrest --type=immediate --target-action=promote --pg1-path=<staged> restore.
Point-in-time:
What this does:
Creates
/var/lib/openg2p-backup-restore/pg-<timestamp>/on the storage node, owned bypostgres.Runs
pgbackrest --type=time --target=... --target-action=promote --pg1-path=<above> restore(or--type=immediatewhen no PIT was supplied).Replays WAL up to the target time when using
--type=time.Stops there. Does not touch the live Postgres instance.
The staged Postgres data directory is a complete, valid PGDATA. You can start a temporary Postgres against it on a different port to inspect, dump tables, or verify before cutting over.
Step 3 — Verify the restore
On the storage node, start a temporary Postgres against the staged PGDATA. On Ubuntu packaging, cluster config lives under /etc/postgresql/…, not inside PGDATA, so a bare pg_ctl -D <staged> often needs a few local files before it will start:
pgBackRest path-mismatch warnings ([032]) during recovery are often noisy but harmless if archive recovery still completes.
Step 4 — Cutover (live PG replacement)
This is the destructive step. Read it, plan a maintenance window, then do it.
Two options:
Option A — full replace (simpler, more downtime)
After at least one successful subsequent backup, you can rm -rf /var/lib/postgresql/16/main.precrash.
Option B — selective table restore (less downtime, more skill)
If only some tables are affected:
Use this when only one or two tables are corrupt and the rest of the database has activity you don't want to lose.
Restore failed mid-way
pgBackRest's restore is atomic at the dataset level — if it fails, the staged dir is incomplete but the live PG is untouched. Read the error, fix (out of disk? wrong target time format?), and re-run.
Upstream reference
The full pgBackRest user guide covers restore variants in detail:
Last updated
Was this helpful?