Why pgBackRest?

pg_dump is fine for small databases, but it’s slow, doesn’t support PITR, and cannot do incremental backups. pgBackRest solves all three:

  • Parallel compression — 10x faster backups than pg_dump on multi-core servers.
  • Incremental/differential — Only back up changed data.
  • Point-in-Time Recovery (PITR) — Restore to any second between backups.
  • Remote backup — Send backups to a dedicated backup server via SSH or S3.

Prerequisites

  • PostgreSQL 12+ running on Linux.
  • At least 2x the database size in free disk space for backups.
  • Root or sudo access.

Step 1: Install pgBackRest

# Ubuntu/Debian
sudo apt install pgbackrest -y

# RHEL/CentOS
sudo yum install pgbackrest -y

Step 2: Configure pgBackRest

/etc/pgbackrest/pgbackrest.conf

[global]
repo1-path=/var/lib/pgbackrest
repo1-retention-full=2
repo1-retention-diff=7
process-max=4
compress-type=zst
compress-level=3
log-level-console=info

[mydb]
pg1-path=/var/lib/postgresql/16/main

Key Settings

SettingPurpose
repo1-pathWhere backups are stored
repo1-retention-full=2Keep 2 full backups
repo1-retention-diff=7Keep 7 differential backups
process-max=4Parallel backup/restore threads
compress-type=zstZstandard compression (fastest)

Step 3: Configure WAL Archiving

Edit /etc/postgresql/16/main/postgresql.conf:

archive_mode = on
archive_command = 'pgbackrest --stanza=mydb archive-push %p'
wal_level = replica
max_wal_senders = 3

Restart PostgreSQL:

sudo systemctl restart postgresql

Step 4: Create Stanza and First Backup

# Initialize the stanza (must run once)
sudo -u postgres pgbackrest --stanza=mydb stanza-create

# Take a full backup
sudo -u postgres pgbackrest --stanza=mydb --type=full backup

# Take a differential backup (daily)
sudo -u postgres pgbackrest --stanza=mydb --type=diff backup

# Check backup status
sudo -u postgres pgbackrest --stanza=mydb info

Step 5: Point-in-Time Recovery (PITR)

Restore to a specific timestamp:

# Stop PostgreSQL
sudo systemctl stop postgresql

# Restore to a specific point in time
sudo -u postgres pgbackrest --stanza=mydb \
  --type=time "--target=2026-02-27 14:30:00" \
  --target-action=promote restore

# Start PostgreSQL
sudo systemctl start postgresql

Automated Backup Schedule (Cron)

# /etc/cron.d/pgbackrest
# Full backup every Sunday at 2 AM
0 2 * * 0 postgres pgbackrest --stanza=mydb --type=full backup
# Differential backup every day at 2 AM (except Sunday)
0 2 * * 1-6 postgres pgbackrest --stanza=mydb --type=diff backup

Troubleshooting

ProblemSolution
”WAL segment not found” during restoreVerify archive_mode=on and archive_command in postgresql.conf; check archive directory
Backup takes too longIncrease process-max for parallelism; use compress-type=zst instead of gz
”stanza already exists” errorThe stanza was already created; this is safe to ignore
Restore fails with permission errorEnsure the postgres user owns the data directory and backup repository
Repository disk fullReduce repo1-retention-full; move repository to larger disk or S3

Summary

  • Use full + differential for a practical weekly/daily schedule.
  • Configure WAL archiving for PITR capability.
  • Use compress-type=zst and process-max=4+ for fast backups.
  • Test restores regularly — a backup you’ve never tested is not a backup.