Database SRE

pgBackRest: Enterprise PostgreSQL Backup and Recovery

Configure pgBackRest for full, differential, and WAL archiving backups with S3 storage and point-in-time recovery

JusDB Team
January 7, 2026
13 min read
188 views

A silent disk failure at 2 AM does not care about your SLA. Neither does the developer who accidentally ran DELETE FROM orders WHERE 1=1; in production. PostgreSQL's built-in tools will get you through the basics, but the moment your database crosses into the hundreds of gigabytes — or you need a reliable point-in-time recovery story — you need something purpose-built. pgBackRest was designed specifically for this class of problem, and it has become the de facto standard for serious PostgreSQL backup operations. This guide walks through everything from initial configuration to S3-backed, parallel, encrypted backups with sub-minute recovery-time granularity.

TL;DR
  • pgBackRest is a dedicated PostgreSQL backup tool supporting full, differential, and incremental backup types plus continuous WAL archiving.
  • A single pgbackrest.conf file controls stanzas, repository paths, S3 credentials, retention, and parallelism.
  • Point-in-time recovery (PITR) is achieved with pgbackrest restore --target combined with WAL archive replay.
  • Parallel processing (--process-max) and delta restore dramatically reduce both backup and restore windows on large databases.
  • The pgbackrest verify command validates backup integrity without a full restore, which should be part of every runbook.

What is pgBackRest?

pgBackRest is an open-source backup and restore tool written specifically for PostgreSQL. Unlike generic tools that treat a database as a collection of files, pgBackRest understands PostgreSQL internals: WAL segments, checksums, tablespaces, and the recovery configuration format. It was originally developed at Crunchy Data and is now maintained by the pgBackRest project under a permissive MIT license.

Compared to Barman (the other widely used PostgreSQL backup manager), pgBackRest takes a different architectural stance. Barman runs as a separate streaming replication client and focuses on catalog management and monitoring. pgBackRest runs directly on the database host (or via SSH to a backup host) and handles parallel compression, encryption, and S3/GCS/Azure object storage natively — without a separate catalog database. For teams that want fewer moving parts and tight S3 integration, pgBackRest is often the cleaner choice.

Key capabilities at a glance:

  • Full, differential, and incremental backup types
  • Continuous WAL archiving with automatic archive gap detection
  • Parallel compression and transfer (pigz, lz4, zstd, bz2)
  • AES-256-CBC encryption at rest
  • Native S3, GCS, and Azure Blob Storage support
  • Delta restore (only changed blocks, dramatically faster for large clusters)
  • Standby backup to offload primary I/O
  • Multi-repository support for redundant storage targets

Architecture

pgBackRest operates using two primary execution contexts: the pg host (where PostgreSQL runs) and the repository host (where backup files are stored). These can be the same machine (local mode) or separate machines connected via SSH (remote mode). In cloud deployments the repository is typically an S3-compatible bucket, eliminating the need for a dedicated backup host entirely.

A stanza is the central organizational unit in pgBackRest. Each stanza represents one PostgreSQL cluster and ties together the database connection parameters, the data directory path, and one or more repository configurations. A single pgBackRest installation can manage multiple stanzas for multiple clusters.

WAL archiving is the backbone of PITR. PostgreSQL writes completed WAL segments to the archive via the archive_command setting in postgresql.conf. pgBackRest receives those segments and stores them in the repository alongside the base backups. During recovery, PostgreSQL requests WAL segments via restore_command and pgBackRest serves them in sequence until the cluster reaches the target LSN or timestamp.

Tip

Always configure archive_status_check = y (the default) so that pgBackRest will abort a backup if WAL archiving is not functioning correctly. An unarchived WAL gap means your PITR window has a hole in it.


Installation and Configuration

On Ubuntu/Debian, install from the PostgreSQL APT repository:

bash
sudo apt-get install pgbackrest

On RHEL/Rocky/AlmaLinux, use the PostgreSQL Yum repository:

bash
sudo dnf install pgbackrest

The primary configuration file lives at /etc/pgbackrest/pgbackrest.conf (or /etc/pgbackrest.conf depending on the distribution package). The structure uses INI-style sections. Below is a production-realistic configuration for a cluster named main backed by S3:

ini
[global]
# Repository backed by S3
repo1-type=s3
repo1-path=/pgbackrest
repo1-s3-bucket=my-company-pg-backups
repo1-s3-endpoint=s3.amazonaws.com
repo1-s3-region=us-east-1
repo1-s3-key=AKIAIOSFODNN7EXAMPLE
repo1-s3-key-secret=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

# Encryption
repo1-cipher-type=aes-256-cbc
repo1-cipher-pass=a-very-long-random-passphrase-stored-in-vault

# Compression
compress-type=lz4
compress-level=6

# Parallel processing
process-max=4

# Retention
repo1-retention-full=4
repo1-retention-diff=14

# Logging
log-level-console=info
log-level-file=detail
log-path=/var/log/pgbackrest

[global:archive-push]
compress-level=3

[main]
pg1-path=/var/lib/postgresql/16/main
pg1-port=5432
pg1-user=postgres

Key parameters explained:

  • repo1-path: The root path inside the repository (bucket prefix for S3).
  • repo1-retention-full: Number of full backups to retain. Older full backups and their associated differentials/incrementals and WAL are automatically expired.
  • repo1-retention-diff: Number of differential backups to retain between full backups.
  • process-max: Number of parallel worker processes for compression and transfer. Set this to the number of available CPU cores, capped at the I/O throughput ceiling of your storage.

Next, configure WAL archiving in postgresql.conf:

ini
wal_level = replica
archive_mode = on
archive_command = 'pgbackrest --stanza=main archive-push %p'
archive_timeout = 60

Reload PostgreSQL after making these changes (pg_ctlcluster 16 main reload or systemctl reload postgresql@16-main).

Create the stanza to initialize the repository structure:

bash
sudo -u postgres pgbackrest --stanza=main stanza-create

Verify that archiving is working before taking any backups:

bash
sudo -u postgres pgbackrest --stanza=main check
Warning

Never skip pgbackrest check after initial setup or after changing archive_command. The check command forces a WAL switch and confirms the segment was successfully received by the repository. If archiving silently fails, your PITR window starts accumulating gaps immediately.


Full, Differential, and WAL Backups

pgBackRest supports three backup types. Understanding the difference is critical for designing a sensible retention and recovery strategy.

Full backup: Copies all data files in the PostgreSQL cluster. This is the baseline every other backup type depends on. Full backups are the most expensive in time and storage but are fully self-contained for restore.

bash
sudo -u postgres pgbackrest --stanza=main --type=full backup

Differential backup: Copies only the pages that changed since the last full backup. Restoring from a differential requires the most recent full backup plus the differential — no intermediate differentials are needed.

bash
sudo -u postgres pgbackrest --stanza=main --type=diff backup

Incremental backup: Copies only the pages that changed since the last backup of any type (full, differential, or incremental). The most storage-efficient option but requires the full chain during restore.

bash
sudo -u postgres pgbackrest --stanza=main --type=incr backup

A typical production schedule uses a weekly full, nightly differentials, and continuous WAL archiving. This provides a maximum restore chain of two backups (full + diff) with granular PITR within each day.

Check the current backup catalog with the info command:

bash
sudo -u postgres pgbackrest --stanza=main info

Example output:

text
stanza: main
    status: ok
    cipher: aes-256-cbc

    db (current)
        wal archive min/max (16): 000000010000000000000001/00000001000000000000002A

        full backup: 20250215-020001F
            timestamp start/stop: 2025-02-15 02:00:01 / 2025-02-15 02:14:37
            wal start/stop: 000000010000000000000005 / 000000010000000000000007
            database size: 142.3GB, database backup size: 142.3GB
            repo1: backup size: 41.8GB

        diff backup: 20250215-020001F_20250216-020001D
            timestamp start/stop: 2025-02-16 02:00:01 / 2025-02-16 02:03:12
            wal start/stop: 000000010000000000000019 / 00000001000000000000001B
            database size: 142.9GB, database backup size: 3.2GB
            repo1: backup size: 987.4MB
Tip

Add --output=json to pgbackrest info to integrate backup catalog data into your monitoring pipeline. The JSON output includes timestamps, sizes, and WAL archive ranges in a machine-readable format that pairs well with Prometheus alerting.


Point-in-Time Recovery

PITR is where pgBackRest earns its place in a production runbook. The restore process has two phases: restoring the base backup files, then replaying WAL segments until the target is reached.

Stop PostgreSQL before any restore operation:

bash
sudo systemctl stop postgresql@16-main

Restore to a specific timestamp (the most common PITR scenario):

bash
sudo -u postgres pgbackrest --stanza=main restore \
  --target="2025-02-16 14:23:00" \
  --target-action=promote \
  --type=time \
  --delta

The --delta flag enables delta restore mode: pgBackRest compares checksums of existing files in the data directory against the backup and only transfers blocks that differ. On large clusters where only a fraction of data changed since the last backup, delta restore can reduce restore time by 80% or more.

Restore to a specific transaction ID:

bash
sudo -u postgres pgbackrest --stanza=main restore \
  --target="12345678" \
  --target-action=promote \
  --type=xid \
  --delta

Restore to a named restore point (created with SELECT pg_create_restore_point('before-migration');):

bash
sudo -u postgres pgbackrest --stanza=main restore \
  --target="before-migration" \
  --target-action=promote \
  --type=name \
  --delta

After the restore command completes, pgBackRest writes a recovery.conf (PostgreSQL 11 and earlier) or postgresql.auto.conf recovery entries (PostgreSQL 12+) with the appropriate restore_command and target settings. Start PostgreSQL and it will begin WAL replay automatically:

bash
sudo systemctl start postgresql@16-main

Monitor the recovery progress in the PostgreSQL log:

bash
sudo journalctl -u postgresql@16-main -f | grep -i "recovery\|redo\|consistent"
Warning

If you are restoring to a target that is earlier than the latest WAL archive, do not start the cluster with --target-action=pause and then manually promote without verifying the recovery target was actually reached. Always check the PostgreSQL log for "recovery stopping before commit" or "recovery stopping after commit" messages to confirm the correct stopping point before promotion.


S3 Storage Configuration

Native S3 support is one of pgBackRest's most operationally important features. Unlike Barman, which relies on external tools for cloud storage, pgBackRest implements the S3 API directly and handles multipart uploads, retry logic, and server-side encryption natively.

For AWS deployments using IAM instance roles instead of static credentials, omit the key parameters and pgBackRest will use the instance metadata endpoint:

ini
[global]
repo1-type=s3
repo1-path=/pgbackrest/production
repo1-s3-bucket=my-company-pg-backups
repo1-s3-endpoint=s3.amazonaws.com
repo1-s3-region=us-east-1
# No repo1-s3-key or repo1-s3-key-secret needed with instance roles

For S3-compatible storage (MinIO, Backblaze B2, Wasabi), set the endpoint to the provider's API URL:

ini
repo1-s3-endpoint=s3.us-west-001.backblazeb2.com
repo1-s3-uri-style=path

For redundant storage across two repositories (S3 primary, local NFS secondary), pgBackRest supports multi-repository configuration:

ini
[global]
repo1-type=s3
repo1-path=/pgbackrest
repo1-s3-bucket=my-company-pg-backups
repo1-s3-endpoint=s3.amazonaws.com
repo1-s3-region=us-east-1
repo1-cipher-type=aes-256-cbc
repo1-cipher-pass=primary-passphrase
repo1-retention-full=4

repo2-type=posix
repo2-path=/mnt/nfs/pgbackrest
repo2-cipher-type=aes-256-cbc
repo2-cipher-pass=secondary-passphrase
repo2-retention-full=2

With this configuration, every backup is written to both repositories simultaneously. The pgbackrest restore command will automatically fall back to repo2 if repo1 is unavailable.


Backup Verification

Taking backups without verifying them is an incomplete strategy. pgBackRest provides the verify command, which validates backup integrity by checking file checksums against the manifest stored in the repository. It does not require a test restore and is safe to run against production repositories:

bash
sudo -u postgres pgbackrest --stanza=main verify

For large repositories, limit verification to recent backups:

bash
sudo -u postgres pgbackrest --stanza=main verify \
  --repo1-retention-full-type=count \
  --repo1-retention-full=1

Schedule verification weekly via cron or a systemd timer. A broken backup discovered before a disaster is a recoverable situation. A broken backup discovered during a disaster is not.

Tip

Automate a test restore to a non-production host monthly. Use pgbackrest restore --delta to a staging cluster and run pg_dumpall --schema-only against it to confirm the catalog is intact. This catches corruption that checksum verification alone cannot detect — such as logically consistent but semantically corrupt data.


pgBackRest vs Barman

Both tools are production-grade. The right choice depends on your operational model:

Feature pgBackRest Barman
Language C / Perl Python
Native S3/GCS/Azure Yes (built-in) Via cloud-barman plugin
Parallel backup/restore Yes (--process-max) Partial (parallel copy)
Encryption at rest AES-256-CBC (built-in) Via external tools
Delta restore Yes No
Catalog / monitoring UI CLI + JSON output Rich CLI + barman-cloud tools
Multi-server management Multiple stanzas per config First-class server catalog

For teams running PostgreSQL on AWS, GCP, or Azure with a preference for minimal infrastructure overhead, pgBackRest's native cloud storage and parallel architecture make it the stronger default. Barman's richer monitoring and catalog tooling makes it a better fit for large DBAs managing many clusters who want a centralized backup server with per-server reporting.


Key Takeaways
  • pgBackRest is the leading dedicated PostgreSQL backup tool, offering full, differential, and incremental backup types with continuous WAL archiving and native S3/GCS/Azure support.
  • The pgbackrest.conf stanza model cleanly separates cluster identity from repository configuration, making it straightforward to manage multiple clusters and multiple storage targets from a single configuration file.
  • Retention is managed automatically via repo1-retention-full and repo1-retention-diff; expired backups and their WAL are pruned from the repository without manual intervention.
  • Point-in-time recovery to a specific timestamp, transaction ID, or named restore point is supported out of the box using pgbackrest restore --target combined with WAL replay.
  • Delta restore (--delta) is a significant operational advantage for large databases, reducing restore time by skipping unchanged data blocks.
  • Parallel processing (--process-max) and compression algorithm selection (lz4, zstd) should be tuned to available hardware to minimize backup windows on large clusters.
  • Run pgbackrest verify on a schedule and periodically perform a test restore to a non-production host — a backup you have never tested restoring is a backup you cannot trust.

Simplify PostgreSQL Operations with JusDB

Configuring and maintaining a production-grade pgBackRest pipeline — keeping WAL archives gap-free, rotating encryption keys, validating restores, and tuning retention policies across multiple clusters — is ongoing operational work that compounds as your database footprint grows. JusDB handles this complexity for you.

JusDB provides managed PostgreSQL with automated backup scheduling, encrypted S3 archiving, one-click point-in-time restore, and continuous WAL monitoring built in. You get the reliability of a well-configured pgBackRest deployment without maintaining the backup infrastructure yourself. Backup verification and retention management are handled automatically, and recovery operations are available through the JusDB dashboard with full audit logging.

If you are running PostgreSQL in production and want enterprise backup guarantees without the operational burden, explore JusDB's managed PostgreSQL service and see how automated backup management fits into your stack.

Share this article