Implementing Point-in-Time Recovery
1. Understanding Point-in-Time Recovery
| Component | Role |
| Base backup | Starting filesystem snapshot |
| WAL archive | All WAL since base |
| Recovery target | Time / xid / LSN / named restore point |
| recovery.signal | Marker 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'
| Target | Meaning |
| time | Stop at timestamp |
| xid | Stop at transaction id |
| lsn | Stop at WAL LSN |
| name | Named restore point |
| immediate | Stop 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.