pgBackRest
Physical backup and PITR automation for self-hosted PostgreSQL 18.4 clusters - stanza config, WAL archiving, restore drills, and Patroni integration.
Search across all documentation pages
Physical backup and PITR automation for self-hosted PostgreSQL 18.4 clusters - stanza config, WAL archiving, restore drills, and Patroni integration.
Quick-reference recipe card - copy-paste ready.
# /etc/pgbackrest/pgbackrest.conf
[global]
repo1-type=s3
repo1-s3-bucket=pg-backups-prod
repo1-s3-region=us-east-1
repo1-retention-full=4
repo1-cipher-type=aes-256-cbc
[main]
pg1-path=/var/lib/postgresql/18/main
pg1-port=5432pgbackrest --stanza=main stanza-create
pgbackrest --stanza=main backup --type=full
pgbackrest --stanza=main checkWhen to reach for this:
Step 1 - Enable archiving in PostgreSQL
ALTER SYSTEM SET archive_mode = on;
ALTER SYSTEM SET archive_command = 'pgbackrest --stanza=main archive-push %p';
SELECT pg_reload_conf();# Verify WAL archive flow
pgbackrest --stanza=main checkStep 2 - Scheduled backup cron
# /etc/cron.d/pgbackrest
0 2 * * 0 postgres pgbackrest --stanza=main backup --type=full
0 2 * * 1-6 postgres pgbackrest --stanza=main backup --type=diffStep 3 - Restore drill to isolated host
# On restore sandbox (empty data directory)
pgbackrest --stanza=main --delta restore
pg_ctl -D /var/lib/postgresql/18/main start
psql -c "SELECT pg_is_in_recovery(), now();"What this demonstrates:
archive-push continuous WAL shipping for PITRcheck validates backup set and archive continuity before you need them--delta restore avoids full re-download when rehearsing monthly| Type | When | Restore data |
|---|---|---|
| full | Weekly baseline | Entire cluster files |
| diff | Daily vs last full | Changed blocks since full |
| incr | Optional intraday | Changed blocks since last backup of any type |
[main]
backup-standby=y
pg2-host=replica.internal
pg2-path=/var/lib/postgresql/18/mainhot_standby = on and is not lagging during backup windowpgbackrest --stanza=main info
pgbackrest --stanza=main verify-- After restore drill
SELECT count(*) FROM pg_database;
SELECT max(created_at) FROM app.orders; -- app-specific sanity rowpg_stat_archiver, alert on failed_count.SHOW data_directory; exactly.repo1-s3-* keys.| Alternative | Use When | Don't Use When |
|---|---|---|
| RDS/Aurora automated backups | Managed AWS Postgres | You need file-level control on self-hosted |
pg_basebackup + manual WAL | Tiny single-node dev | Production PITR with retention policy |
| Barman | Team already standardized on Barman | Greenfield pgBackRest adoption with S3-native ops |
No. Physical backup plus PITR is for disaster recovery. Keep periodic pg_dump for logical table-level restore and cross-major upgrades.
repo1-retention-full=4 keeps four full backups. Add WAL retention policy aligned to RPO (often 7-30 days). Document in DR runbook.
Physical restore stays on same major. Major upgrades use pg_upgrade or logical replication, not pgBackRest cross-major restore.
checkStack versions: This page was written for PostgreSQL 18.4, pgBackRest 2.55+, and Patroni 4.x on self-hosted clusters.
Reviewed by Chris St. John·Last updated Jul 16, 2026