Implementing Point-in-Time Recovery

1. Understanding Point-in-Time Recovery

ComponentRole
Base backupStarting filesystem snapshot
WAL archiveAll WAL since base
Recovery targetTime / xid / LSN / named restore point
recovery.signalMarker that triggers recovery mode

2. Enabling WAL Archiving

# postgresql.conf
archive_mode    = on
archive_command = 'test ! -f /wal_archive/%f && cp %p /wal_archive/%f'

3. Configuring archive_command

archive_command = 'rsync %p backup-host:/wal_archive/%f'
# Production: use pgBackRest / WAL-G / barman instead of hand-rolling.

4. Setting wal_level

wal_level = replica         # minimum for PITR
# (logical also works)

5. Creating Base Backup

pg_basebackup -D /backups/base -Ft -z -P -X stream -U repl

6. Stopping Base Backup

-- Low-level (non-exclusive, PG 15+ uses base backup protocol)
SELECT pg_backup_start('label', false);   -- PG 15+ (renamed from pg_start_backup)
-- copy data directory ...
SELECT pg_backup_stop();

7. Restoring Base Backup

rm -rf $PGDATA
tar -xzf /backups/base/base.tar.gz -C $PGDATA

8. Creating recovery.signal File

touch $PGDATA/recovery.signal

9. Configuring restore_command

# postgresql.conf (or .auto.conf)
restore_command         = 'cp /wal_archive/%f %p'
recovery_target_action  = 'promote'

10. Setting recovery_target_time

recovery_target_time = '2025-03-15 14:23:00+00'

11. Setting recovery_target_xid

recovery_target_xid       = '1234567'
recovery_target_inclusive = false

12. Setting recovery_target_name

recovery_target_name = 'pre_deploy'
TargetMeaning
timeStop at timestamp
xidStop at transaction id
lsnStop at WAL LSN
nameNamed restore point
immediateStop as soon as consistent

13. Creating Restore Points

SELECT pg_create_restore_point('pre_deploy');

14. Starting Recovery

pg_ctl -D $PGDATA start
tail -f $PGDATA/log/postgresql-*.log    # watch for "recovery complete"

15. Verifying Recovery

SELECT pg_is_in_recovery();          -- f after promote
SELECT pg_last_wal_replay_lsn();
SELECT pg_last_xact_replay_timestamp();
Warning: Always perform PITR on a copy. Once you cross the recovery target, you cannot go further back without restoring the base again.