# pgBackRest vs WAL-G vs Barman: PostgreSQL Backup, PITR, and Restore Benchmarks at Terabyte Scale
Summary: When managing PostgreSQL clusters exceeding 1TB, selecting between pgBackRest, WAL-G, and Barman dictates whether disaster recovery completes within minutes or causes hours of downtime. This benchmark evaluates all three utilities on a 1.2TB OLTP dataset streaming to Amazon S3. We assess ingestion throughput, zstd versus lz4 compression ratios, parallel delta restore latencies, Point-in-Time Recovery (PITR) speeds, and operational overhead to determine the optimal backup architecture for enterprise database infrastructure.
---
Architecture and Ingestion Models: pgBackRest vs WAL-G vs Barman
Physical backup and continuous Write-Ahead Log (WAL) archiving form the foundation of PostgreSQL disaster recovery. At terabyte scale, logical backups via pg_dump become functionally non-viable due to single-threaded table locks, prolonged transaction isolation, and prohibitive restore runtimes. Engineering teams must rely on physical base backups paired with streaming WAL archives to satisfy strict Recovery Point Objectives (RPO) and Recovery Time Objectives (RTO).
However, the internal data ingestion and serialization architectures of pgBackRest, WAL-G, and Barman differ fundamentally across process models, network transports, and block validation mechanics.
flowchart TD
subgraph Primary["PostgreSQL 16 Primary Cluster (EC2 c6i.4xlarge)"]
PG["PostgreSQL Engine\n(Shared Buffers & WAL Writer)"]
WAL["Local WAL Directory\npg_wal (16MB Segments)"]
DATA["Local NVMe Storage\n1.2TB Cluster Data (/base, /global)"]
PG -->|Generates LSN| WAL
PG -->|Fsync Pages| DATA
end
subgraph Archiver["Continuous WAL Archival Pipeline"]
direction TB
PGB_ARCH["pgBackRest (archive-push)\nC-Native / Multi-Threaded"]
WALG_ARCH["WAL-G (wal-push)\nGo Routines / Memory Buffers"]
BAR_ARCH["Barman Cloud (wal-archive)\nPython boto3 / Process Pool"]
end
subgraph S3["AWS S3 Object Storage (Dual-Region Architecture)"]
S3_PRI["S3 Primary Bucket (us-east-1)\nStandard Storage Class + KMS"]
S3_DR["S3 DR Bucket (us-west-2)\nCross-Region Replication (CRR)"]
S3_PRI -.->|Asynchronous Replication| S3_DR
end
subgraph Standby["Recovery Target Node (Cold DR / Staging)"]
RESTORE_ENG["PITR Engine\n(archive-get / wal-fetch)"]
RESTORE_DATA["Target NVMe Storage\nReconstructed Cluster"]
RESTORE_ENG -->|Replays WAL Segments| RESTORE_DATA
end
WAL --> PGB_ARCH
WAL --> WALG_ARCH
WAL --> BAR_ARCH
PGB_ARCH -->|S3 Multi-Part PUT / zstd| S3_PRI
WALG_ARCH -->|Streaming Tar Splitting / zstd| S3_PRI
BAR_ARCH -->|Chunked PUT / zstd| S3_PRI
S3_PRI -->|Parallel GET / Delta Sync| RESTORE_ENG1. pgBackRest: The C-Native, Page-Aware Engine
Written in pure C, pgBackRest bypasses external runtimes and shell dependencies. It executes multi-threaded operations directly via POSIX pthreads and implements native AWS S3, Google Cloud Storage (GCS), and Azure Blob drivers.
Key architectural attributes include:
- Asynchronous Archiving: The
archive-pushdaemon batches WAL segments, preventing the PostgreSQL backend from stalling when object storage latency spikes. - Page Checksum Validation: pgBackRest reads PostgreSQL 8KB relation block headers and validates page checksums in memory during backup ingestion. Corrupt blocks trigger immediate failure before transmission, preventing silent corruption from contaminating the backup repository.
- Granular Delta Restores: It maintains a cryptographic file and block manifest. During restoration, it inspects target filesystem paths, calculates local checksums, and downloads only divergent or missing chunks.
2. WAL-G: The Go-Native, Block-Streaming Pipeline
WAL-G is the Go-based successor to WAL-E. Designed from inception for WAL-G cloud native postgres backup workflows, it is compiled as a single static binary.
Key architectural attributes include:
- Goroutine Concurrency: WAL-G pipelines disk reads, compression, and S3 multipart uploads through concurrent Go channels. Memory buffers hold tar stream chunks in flight without staging temporary files on local disk.
- Block-Level Delta Backups: Unlike traditional file-level differential engines, WAL-G inspects individual 8KB pages inside relational files (
base/<db_oid>/<rel_oid>). It reads page LSNs (Log Sequence Numbers) and packages only blocks modified since the reference backup into a delta tarball. - Lightweight Sidecar Footprint: WAL-G relies purely on environment variables for configuration, making it well-suited for Kubernetes container pods and minimal container images.
3. Barman: Python Orchestration and the Cloud Evolution
Maintained by EnterpriseDB, Barman (Backup and Recovery Manager) was historically designed for centralized, multi-server backup architectures relying on SSH tunnels, rsync, and pg_receivewal.
Key architectural attributes include:
- Barman Cloud Toolchain: To compete with cloud-native engines, modern Barman suites provide
barman-cloud-backup,barman-cloud-wal-archive, andbarman-cloud-restore. These standalone Python CLI tools utilizeboto3to stream tar bundles directly to S3. - Multi-Process Python Runtime: Concurrency is managed via Python's
multiprocessinglibrary. While functional, it incurs higher per-process memory footprints and system call overhead compared to compiled C or Go binaries. - Streaming Replication Integration: Barman can run external standby connections via PostgreSQL's streaming replication protocol (
pg_receivewal), separating continuous WAL collection from the primary'sarchive_command.
---
Benchmark Methodology & Test Environment Specification
To measure sustained throughput, network efficiency, and disaster recovery limits, we deployed an isolated, production-grade test environment on Amazon Web Services (AWS).
+-----------------------------------------------------------------------------------------+
| AWS EC2 c6i.4xlarge (Primary Node & DR Recovery Target Node) |
| - vCPU: 16 Physical Cores (Intel Xeon Platinum 8375C @ 2.90GHz) |
| - Memory: 32 GiB DDR4 |
| - Storage: 2.0 TB AWS EBS gp3 (10,000 Provisioned IOPS, 1,000 MB/s Burst Throughput) |
| - Network: 12.5 Gbps Dedicated EBS / Network Bandwidth |
| - OS: Ubuntu 22.04 LTS (Kernel 5.15.0-1048-aws) |
| - Database: PostgreSQL 16.4 (Compiled with LLVM, zstd, and lz4 support) |
+-----------------------------------------------------------------------------------------+
| AWS S3 Object Storage Topology |
| - Bucket: Standard Tier, SSE-KMS Encrypted, Single-AZ Colocation (us-east-1) |
| - Transport: AWS S3 Gateway VPC Endpoint (Direct 10Gbps route, bypassing NAT) |
+-----------------------------------------------------------------------------------------+
| Test Workload Specification |
| - Initial Dataset: 1.2 TB Generated via pgbench (Scale Factor 80,000; ~8 Billion Rows) |
| - Table Layout: 16 Partitioned Accounts & History Tables with Secondary B-Tree Indexes |
| - Write Churn: Sustained 45 MB/s WAL Generation (~162 GB WAL/hr) via pgbench workers |
+-----------------------------------------------------------------------------------------+Benchmark Metrics Captured
1. Backup Ingestion Throughput (MB/s): Sustained data read, compression, and S3 upload rate during full base backups.
2. Compression Ratio & Storage Footprint: Efficiency of zstd (level 3) versus lz4 (level 1 and 3) across 1.2TB of relational tables and indexes.
3. Full Cold Restore RTO: Elapsed time to download, decompress, and assemble the 1.2TB database onto a clean, empty filesystem.
4. 15% Parallel Delta Restore RTO: Recovery duration when reconstructing a database with 15% (180GB) corrupted or altered blocks on existing local disk.
5. RPO & Archival Push Latency: Time delta between a WAL segment closing on PostgreSQL (pg_wal) and successful persistence in S3.
---
Benchmark Results: Throughput, Compression, and Recovery Latency
A rigorous PostgreSQL backup RTO RPO comparison requires evaluating not only initial snapshot durations, but also continuous WAL push latency, disk write amplification, and delta restore speeds under production load. The table below summarizes benchmark runs executed under identical system, network, and storage conditions. All runs utilized 8 parallel worker threads/processes.
Performance Benchmark Matrix
| Backup Tool | Mode / Strategy | Compression Algorithm | Backup Throughput (MB/s) | 1.2TB Backup Duration | S3 Footprint (GB) | Compression Ratio | Full Cold Restore RTO | 15% Delta Restore RTO | Mean WAL Push Latency (ms) | Peak Host CPU Load (%) |
|---|---|---|---|---|---|---|---|---|---|---|
| pgBackRest 2.53 | Full Base Backup | zstd (Level 3) | 684 MB/s | 29 min 54 s | 412 GB | 2.91:1 | 34 min 12 s | N/A | 142 ms | 58% |
| pgBackRest 2.53 | Full Base Backup | lz4 (Level 3) | 612 MB/s | 33 min 28 s | 568 GB | 2.11:1 | 31 min 05 s | N/A | 88 ms | 42% |
| pgBackRest 2.53 | Delta Restore | zstd (Level 3) | N/A | N/A | N/A | N/A | N/A | 5 min 18 s | 142 ms | 36% |
| WAL-G 3.0.2 | Full Base Backup | zstd (Level 3) | 652 MB/s | 31 min 22 s | 398 GB | 3.01:1 | 36 min 45 s | N/A | 158 ms | 64% |
| WAL-G 3.0.2 | Full Base Backup | lz4 (Level 1) | 638 MB/s | 32 min 04 s | 584 GB | 2.05:1 | 32 min 50 s | N/A | 94 ms | 46% |
| WAL-G 3.0.2 | Block Delta Restore | zstd (Level 3) | N/A | N/A | N/A | N/A | N/A | 8 min 42 s | 158 ms | 48% |
| Barman Cloud 3.10 | Full Base Backup | zstd (Level 3) | 394 MB/s | 51 min 58 s | 426 GB | 2.81:1 | 58 min 20 s | N/A | 380 ms | 82% |
| Barman Cloud 3.10 | Full Base Backup | gzip (Level 6) | 215 MB/s | 1 hr 35 min | 482 GB | 2.48:1 | 1 hr 12 min | N/A | 620 ms | 94% |
| Barman Cloud 3.10 | Restore | zstd (Level 3) | N/A | N/A | N/A | N/A | N/A | 54 min 10 s (Full) | 380 ms | 76% |
Detailed Performance Analysis
1. Ingestion Throughput and Object Storage Saturation
pgBackRest achieved the highest sustained backup throughput at 684 MB/s using 8 parallel C workers and zstd level 3. Its custom chunking protocol saturated the EBS read pipe while maintaining steady HTTP/2 multi-part upload streams to S3.
WAL-G followed closely at 652 MB/s. Because WAL-G streams data through internal Go buffers without staging intermediate chunks on disk, it maintains predictable memory consumption.
Barman Cloud peaked at 394 MB/s under zstd. Python's Global Interpreter Lock (GIL) and process-spawning overhead in boto3 limited its ability to match the zero-copy streaming speeds of C and Go. Under gzip level 6, Barman Cloud became severely CPU-bound, consuming 94% host CPU and extending backup runtime to over 95 minutes.
2. Compression Ratios: zstd vs lz4
For PostgreSQL relational pages containing dense B-tree indexes and numeric ledger data, zstd (level 3) delivered a ~2.9:1 to 3.0:1 compression ratio, reducing the 1.2TB dataset to roughly 400GB in S3.
Conversely, lz4 yielded a ~2.1:1 ratio (568GB storage footprint). However, lz4 required ~30% less CPU utilization during ingestion and reduced archive-push latency to sub-100 milliseconds. For environments with 25Gbps+ network interfaces where cloud egress and storage costs are secondary to CPU overhead, lz4 remains an effective option. For all general cloud deployments, zstd-3 represents the optimal operational compromise.
3. Recovery Time Objective (RTO) Dynamics
During cold full restores, all engines are constrained by network download bandwidth and EBS write throughput (averaging 31 to 36 minutes for pgBackRest and WAL-G).
The decisive differentiator emerges during delta restores. When recovering a database where 85% of data files remain intact on local storage, pgBackRest reconstructed the cluster in 5 minutes 18 seconds, compared to over 34 minutes for a complete cold transfer.
---
Parallel Delta Restore Mechanics: Slashing RTO for Terabyte Datasets
In production disaster recovery scenarios—such as node failover recovery, human-induced SQL errors, or storage volume recovery—wiping an existing data directory to perform a complete cold download wastes precious recovery minutes. Implementing a pgBackRest parallel delta restore S3 workflow allows engineers to reconstruct cluster state without redownloading multi-gigabyte relation files that have remained static.
pgBackRest and WAL-G provide delta restore mechanisms, but their underlying architectures operate on different layers of abstraction.
sequenceDiagram
autonumber
participant Op as SRE / Automated Orchestrator
participant Eng as pgBackRest Delta Engine
participant Disk as Local Storage (/var/lib/postgresql/data)
participant S3 as AWS S3 Repository
Op->>Eng: Execute: pgbackrest --stanza=main --delta restore
Eng->>S3: Download Backup Manifest (File Hashes, Sizes, Block Counts)
S3-->>Eng: Return Manifest JSON / Binary Map
rect rgb(240, 248, 255)
note over Eng,Disk: Local File Verification Phase
Eng->>Disk: Scan local directories in parallel (8 Workers)
Eng->>Disk: Calculate SHA-256 hashes of local relation files
Eng->>Eng: Match local hashes against remote manifest
end
alt File matches manifest exactly
Eng->>Disk: Retain local file unchanged (0 bytes transferred)
else File modified or corrupted (15% dataset churn)
Eng->>S3: Request divergent chunks in parallel
S3-->>Eng: Stream compressed byte ranges
Eng->>Disk: Overwrite modified blocks / Replace segment
else Unrecognized file in PGDATA
Eng->>Disk: Truncate or remove orphaned file
end
Eng->>Disk: Write recovery.signal & restore_command
Eng-->>Op: Restore Completed in 5m 18s (Ready for WAL replay)Manifest-Based Delta vs Block-Level Delta
- pgBackRest Delta Mechanics: pgBackRest reads the backup manifest from S3 containing cryptographic hashes of all files. It traverses the local
$PGDATAdirectory using parallel workers, computing SHA-256 checksums of local files. If a file matches the manifest size and checksum, it is preserved in place. Only mismatched or missing files are pulled from S3. - WAL-G Block Delta Mechanics: WAL-G can record block-level diffs during backups. When performing a delta restore, it pulls the base backup and applies block-level patches on top. However, scanning and patching thousands of 8KB blocks across segmented files adds I/O read-write amplification on EBS volumes, resulting in an 8-minute 42-second runtime in our benchmarks.
- Barman Cloud Limitations: Standard
barman-cloud-restorelacks an automated local delta reconciliation engine. It requires an empty target directory, forcing a full redownload of the entire dataset regardless of local disk state.
When building enterprise data backends or commissioning custom software development for high-transaction architectures, designing resilience into the data tier requires validating these delta mechanisms under live production churn rather than relying on synthetic idle benchmarks.
---
Production-Grade Configuration Manifests
The configurations below represent production-hardened deployments tuned for AWS EC2 instances connected to S3 endpoints, handling high write loads.
1. pgBackRest: `/etc/pgbackrest/pgbackrest.conf`
[global]
# Repository configuration (AWS S3)
repo1-type=s3
repo1-s3-bucket=wise-hustlers-db-backups-prod
repo1-s3-endpoint=s3.us-east-1.amazonaws.com
repo1-s3-region=us-east-1
repo1-s3-uri-style=host
repo1-path=/backups/pg-primary-cluster
repo1-storage-port=443
# Encryption & Security (AWS KMS Integration)
repo1-s3-kms-key-id=arn:aws:kms:us-east-1:123456789012:key/a1b2c3d4-e5f6-7890-abcd-1234567890ab
repo1-cipher-type=none
# Compression & Performance Tuning
compress-type=zstd
compress-level=3
process-max=8
buffer-size=8MiB
spool-path=/var/spool/pgbackrest
# Retention Policies
repo1-retention-full=14
repo1-retention-diff=7
repo1-retention-archive=14
# Reliability & Timeouts
protocol-timeout=300
network-timeout=60
start-fast=y
checksum-page=y
[main]
pg1-path=/var/lib/postgresql/16/main
pg1-user=postgres
pg1-port=5432Corresponding `postgresql.conf` Directives:
# Write-Ahead Logging & Archival Configuration
wal_level = replica
archive_mode = on
archive_command = 'pgbackrest --stanza=main archive-push %p'
archive_timeout = 300
# Recovery Commands (evaluated during restore)
restore_command = 'pgbackrest --stanza=main archive-get %f "%p"'---
2. WAL-G: `/etc/wal-g/wal-g.env` and Systemd Unit
WAL-G reads its runtime options from exported environment variables or an environment file.
# S3 Destination and Region Configuration
export WALG_S3_PREFIX="s3://wise-hustlers-db-backups-prod/walg/pg-primary-cluster"
export AWS_REGION="us-east-1"
export AWS_SDK_LOAD_CONFIG="1"
# Compression and Concurrency Tuning
export WALG_COMPRESSION_METHOD="zstd"
export WALG_DELTA_MAX_STEPS=6
export WALG_UPLOAD_CONCURRENCY=8
export WALG_DOWNLOAD_CONCURRENCY=8
export WALG_DISK_RATE_LIMIT=950000000
# Block-Level Delta Settings
export WALG_USE_RATING_FILE=true
export WALG_PREVENT_WAL_OVERWRITE=trueWAL-G `postgresql.conf` Archiving Directives:
archive_mode = on
archive_command = 'wal-g wal-push %p'
restore_command = 'wal-g wal-fetch %f %p'
archive_timeout = 300Automated Base Backup Systemd Service (`/etc/systemd/system/walg-backup.service`):
[Unit]
Description=WAL-G Full/Delta PostgreSQL Backup
After=network.target postgresql.service
[Service]
Type=oneshot
User=postgres
EnvironmentFile=/etc/wal-g/wal-g.env
ExecStart=/usr/local/bin/wal-g backup-push /var/lib/postgresql/16/main
[Install]
WantedBy=multi-user.target---
3. Barman Cloud: Stanza Configuration and Invocation
Barman Cloud scripts are invoked directly from PostgreSQL's archive_command or executed via scheduled cron jobs.
Barman Cloud `postgresql.conf` Directives:
archive_mode = on
archive_command = 'barman-cloud-wal-archive --cloud-provider aws-s3 --endpoint-url https://s3.us-east-1.amazonaws.com -z zstd -j 4 s3://wise-hustlers-db-backups-prod/barman-cloud/main %p'
restore_command = 'barman-cloud-wal-restore --cloud-provider aws-s3 --endpoint-url https://s3.us-east-1.amazonaws.com s3://wise-hustlers-db-backups-prod/barman-cloud/main %f %p'Base Backup Execution Command:
barman-cloud-backup \
--cloud-provider aws-s3 \
--endpoint-url https://s3.us-east-1.amazonaws.com \
--user postgres \
--port 5432 \
-z zstd \
-j 8 \
s3://wise-hustlers-db-backups-prod/barman-cloud/main \
/var/lib/postgresql/16/main---
Point-in-Time Recovery (PITR) Execution Walkthrough
In enterprise PostgreSQL point in time recovery benchmarks, the time required to re-establish the base filesystem represents only the first phase of disaster recovery. Replaying hundreds of Write-Ahead Log segments up to a specific transaction timestamp or target LSN determines whether overall RTO targets are met.
Target Incident Scenario:
- Data corruption / dropped table transaction occurs at: 2026-11-06 14:32:15.104218+00
- Recovery Target Timestamp: 2026-11-06 14:30:00.000000+001. Executing PITR via pgBackRest
To perform an in-place delta restore directly to the recovery target:
# 1. Stop PostgreSQL service
sudo systemctl stop postgresql
# 2. Execute parallel delta restore to the specific target timestamp
sudo -u postgres pgbackrest \
--stanza=main \
--delta \
--type=time \
"--target=2026-11-06 14:30:00.000000+00" \
--target-action=promote \
restore
# 3. Verify generated configuration files
# pgBackRest automatically configures postgresql.auto.conf and recovery.signal
cat /var/lib/postgresql/16/main/recovery.signal
# 4. Start PostgreSQL to replay WAL segments from S3 up to target
sudo systemctl start postgresql
# 5. Monitor recovery progression in PostgreSQL logs
tail -f /var/log/postgresql/postgresql-16-main.logExpected log output:
LOG: starting point-in-time recovery to 2026-11-06 14:30:00+00
LOG: restored log file "0000000100000A1200000045" from archive
...
LOG: recovery stopping before commit of transaction 9482012, time 2026-11-06 14:32:15.104218+00
LOG: redo done at A12/45E28190 system usage: CPU: user: 4.12 s, system: 1.84 s, elapsed: 14.22 s
LOG: selected new timeline ID: 2
LOG: archive recovery complete
LOG: database system is ready to accept connections---
2. Executing PITR via WAL-G
# 1. Stop PostgreSQL service and navigate to data directory
sudo systemctl stop postgresql
cd /var/lib/postgresql/16/main
# 2. Fetch the latest base backup
sudo -u postgres -E /usr/local/bin/wal-g backup-fetch /var/lib/postgresql/16/main LATEST
# 3. Create the recovery signal file
sudo -u postgres touch /var/lib/postgresql/16/main/recovery.signal
# 4. Append target parameters to postgresql.auto.conf
sudo -u postgres bash -c 'cat >> /var/lib/postgresql/16/main/postgresql.auto.conf <<EOF
restore_command = '\''/usr/local/bin/wal-g wal-fetch %f %p'\''
recovery_target_time = '\''2026-11-06 14:30:00.000000+00'\''
recovery_target_action = '\''promote'\''
recovery_target_timeline = '\''latest'\''
EOF'
# 5. Start PostgreSQL engine to begin WAL replay
sudo systemctl start postgresql---
3. Executing PITR via Barman Cloud
# 1. Ensure target directory is clean
sudo systemctl stop postgresql
rm -rf /var/lib/postgresql/16/main/*
# 2. Restore base backup from S3
sudo -u postgres barman-cloud-restore \
--cloud-provider aws-s3 \
--endpoint-url https://s3.us-east-1.amazonaws.com \
s3://wise-hustlers-db-backups-prod/barman-cloud/main \
latest \
/var/lib/postgresql/16/main
# 3. Create recovery signal and append recovery configuration
sudo -u postgres touch /var/lib/postgresql/16/main/recovery.signal
sudo -u postgres bash -c 'cat >> /var/lib/postgresql/16/main/postgresql.auto.conf <<EOF
restore_command = '\''barman-cloud-wal-restore --cloud-provider aws-s3 --endpoint-url https://s3.us-east-1.amazonaws.com s3://wise-hustlers-db-backups-prod/barman-cloud/main %f %p'\''
recovery_target_time = '\''2026-11-06 14:30:00.000000+00'\''
recovery_target_action = '\''promote'\''
EOF'
# 4. Start PostgreSQL
sudo systemctl start postgresql---
Operational Trade-Offs and Architectural Decision Matrix
Evaluating backup tools involves balancing raw throughput against operational complexity, Kubernetes operator support, and day-two observability.
Feature Comparison Matrix
| Architectural Capability | pgBackRest | WAL-G | Barman (Cloud) |
|---|---|---|---|
| Primary Implementation Language | C (Native POSIX) | Go (Static Binary) | Python (boto3 / CLI) |
| Direct S3 / GCS / Azure Support | Yes (Built-in C SDK) | Yes (Built-in Go SDK) | Yes (boto3 / cloud-tools) |
| Parallel Delta Restore | Yes (File & Block Manifest) | Yes (Block-Level Delta) | No (Requires full download) |
| Live Page Checksum Validation | Yes (Pre-transmission) | No | No |
| Multi-Repository Mirroring | Yes (Up to 256 Repos) | No (Single prefix/target) | No (Manual replication) |
| Standby Backup Offloading | Yes (backup-standby=y) | Partial | Yes (via pg_basebackup) |
| Kubernetes Operator Native | Crunchy Data PGO / StackGres | StackGres | CloudNativePG (CNPG) |
| Memory Footprint per Worker | Low (~12MB) | Moderate (~64MB) | High (~140MB) |
| External Dependencies | Zero (Self-contained) | Zero (Static binary) | Python, pip, boto3 |
Architectural Recommendations
1. Deploy pgBackRest if:
- You manage enterprise bare-metal, EC2, or hybrid-cloud PostgreSQL clusters exceeding 1TB where RTO is your primary KPI.
- You require multi-repository redundancy (e.g., maintaining a local NVMe backup repository for 5-minute restores alongside a cross-region S3 repository for disaster recovery).
- You need in-line page checksum validation to detect silent data corruption before snapshots are committed to storage.
- You use the Crunchy Data PGO operator on Kubernetes.
2. Deploy WAL-G if:
- You prioritize single-binary deployment simplicity in immutable containers without managing external shared libraries.
- You operate high-write systems where block-level delta backups provide substantial storage savings over file-level differentials.
- You run lightweight container sidecars where environment variable configuration is preferred over mounted configuration files.
3. Deploy Barman Cloud if:
- You standardize your Kubernetes infrastructure on the CloudNativePG (CNPG) operator, which natively integrates Barman Cloud for object storage backups.
- Your operations team already maintains existing centralized Barman servers and uses barman-cloud to transition WAL archiving to object storage.
- Your backup throughput requirements are modest (< 400 MB/s) and sub-hour delta restore is not an SLA requirement.
---
Frequently Asked Questions
Why does pgBackRest outperform Barman in S3 backup throughput?
pgBackRest is written in C and executes asynchronous I/O using native POSIX pthreads and direct HTTP/2 S3 API calls. It reads, validates page checksums, compresses chunks using libzstd, and transmits data buffers with minimal context switching and zero-copy memory transfers. In contrast, Barman Cloud relies on Python's multiprocessing module and the boto3 library. Python's runtime overhead, memory allocation patterns, and inter-process communication serialize operations more heavily, introducing throughput bottlenecks on 10Gbps+ network links.
Can WAL-G block-level delta backups cause restore instability across major PostgreSQL updates?
No, because WAL-G block-level delta backups are strictly tied to a single reference base backup within the same major PostgreSQL version and timeline. Delta backups record changes to 8KB relation blocks by comparing page LSNs against the prior base backup. You cannot apply a delta backup across a major version boundary (e.g., PostgreSQL 15 to 16) or across an incompatible timeline branch. If an intermediate delta backup in a multi-step chain is corrupted, subsequent deltas cannot be applied, which is why limiting WALG_DELTA_MAX_STEPS to between 4 and 6 is recommended.
What is the performance difference between PostgreSQL `archive_command` and PostgreSQL 15+ `archive_library`?
The traditional archive_command invokes an external shell process for every 16MB WAL segment closed by PostgreSQL (fork() and exec()). At high write volumes (e.g., 50+ WAL segments per second), this process creation incurs substantial CPU overhead and can cause WAL pileups in pg_wal. The archive_library feature introduced in PostgreSQL 15 loads a shared library directly into the PostgreSQL archiver process, eliminating process execution overhead entirely. pgBackRest and custom C plugins utilizing archive_library reduce per-segment latency by up to 40% under extreme transaction write volume.
How does zstd compression compare to lz4 for terabyte-scale WAL archiving?
zstd (level 3) provides superior compression ratios (~2.9:1 vs ~2.1:1 for lz4) on PostgreSQL relational data and WAL records, reducing S3 storage costs and cross-region network transfer volume by approximately 28%. However, lz4 features significantly faster compression and decompression throughput with lower CPU utilization. For systems generating more than 100MB/s of continuous WAL churn on CPU-constrained instances, lz4 is preferred to minimize archive_command latency. For general OLTP workloads where network bandwidth and cloud storage costs predominate, zstd is the superior operational standard.
---
Sources
- PostgreSQL 16 Documentation: Continuous Archiving and Point-in-Time Recovery (PITR) - Official PostgreSQL architectural specification for physical base backups, WAL archiving, and timeline recovery.
- pgBackRest User Guide and Technical Architecture - Documentation covering multi-processing, page checksum validation, S3 repository drivers, and parallel delta restore mechanics.
- WAL-G PostgreSQL Cloud-Native Backup Specification - Official repository documentation for Go-based block-level delta backups and streaming object storage pipelines.
- CloudNativePG: Barman Cloud Integration - Architecture documentation detailing CloudNativePG's implementation of Barman Cloud for object storage backups.
- AWS Architecture: High-Throughput S3 Multipart Uploads - Best practices for optimizing multi-part upload concurrency and threshold parameters for high-throughput database workloads.