For the complete documentation index, see llms.txt. This page is also available as Markdown.

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.pass passphrase from your keystore.

--type=immediate / --type=time are pgBackRest flags set by the orchestrator. They are not arguments to openg2p-backup.sh. Omit --point-in-time for latest; pass --point-in-time '…' for PITR. Both paths always include --target-action=promote together with --type.

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-run

Reads 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:

  1. Creates /var/lib/openg2p-backup-restore/pg-<timestamp>/ on the storage node, owned by postgres.

  2. Runs pgbackrest --type=time --target=... --target-action=promote --pg1-path=<above> restore (or --type=immediate when no PIT was supplied).

  3. Replays WAL up to the target time when using --type=time.

  4. 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?