This episode brings pgBackRest to terabyte scale: parallel backup leveraging many resources, tuning process-max based on CPU and I/O, restore optimization with --delta, and benchmarks measuring backup/restore duration against database size. Optimization starts from measured data, not guesses.

Everything we've learned works beautifully for small-to-medium databases. But when data crosses into hundreds of gigabytes to terabytes, the rules change: one huge file, many small files, limited bandwidth, and narrow backup windows. In episode 19 we bring pgBackRest to that scale — with measured parallelism, delta optimization, and benchmarks that turn intuition into numbers.
This episode's philosophy: optimization without measurement is an opinion. Every decision — how much process-max, whether a higher compression level is needed, when to use --delta — must be backed by data from your own benchmarks.
On a terabyte database, backup time is determined by:
Test progressively on the same database in the same window:
sudo -u postgres pgbackrest --stanza=main --process-max=2 backup --type=diff
sudo -u postgres pgbackrest --stanza=main --process-max=4 backup --type=diff
sudo -u postgres pgbackrest --stanza=main --process-max=8 backup --type=diffNote the duration of each run (shown in the command output). The typical curve: duration drops then flattens — at the flattening point the bottleneck shifts from CPU to I/O/network, and adding more process-max no longer helps.
Tip
A rule of thumb to start: process-max around half the core count if storage is local NVMe, or lower if writing to NFS/S3 with limited bandwidth. Increase gradually and stop at the flattening point — not at the maximum.
A process-max that's too high disturbs the production workload. Two strategies:
process-max when traffic is low (episode 10).--process-max during peak hours, higher during the backup window — without changing the config:sudo -u postgres pgbackrest --stanza=main --process-max=16 backup --type=fullFor large databases, a full restore (copying every file from the repository) can take hours. --delta (episode 8) changes the game: it compares local files against the backup and only overwrites what differs. For a cluster that's mostly intact, this can cut RTO dramatically.
sudo -u postgres pgbackrest --stanza=main --delta restoreFor --delta to work optimally:
data_checksums=on) so delta compares with confidence.--delta is still used — it only speeds up file copying, not the recovery logic.In an HA cluster (episode 18), delta restore becomes the trusted weapon for bootstrapping new nodes: restore to the existing PGDATA, then stream a catch-up from the primary. The time to grow a node drops from "hours" to "minutes."
A good benchmark has three traits: a single variable, real data, and repetition. Design a recording table:
CREATE TABLE bench_backup (
dt timestamptz default now(),
db_size_gb numeric,
type text,
process_max int,
duration_sec numeric
);Then record each backup with a query to pg_database_size:
psql -U postgres -tAc \
"INSERT INTO bench_backup (db_size_gb, type, process_max, duration_sec)
VALUES (round(pg_database_size('aplikasi')/1e9,2), 'full', 8, $DURATION);"Plot duration against size for each type. The patterns you must understand:
Size (GB) Full (min) Diff (min) Restore (min)
250 18 4 21
500 36 5 42
1000 72 6 85From this data, the RTO estimate in episode 10 can be calculated instead of guessed: if restoring 1 TB takes 85 minutes, your RTO is at least that number.
Warning
A single benchmark isn't enough — hardware, load, and data change. Make benchmarks run periodically (monthly, from cron) and store the results. A drastic change in duration for the same size is an early signal of storage degradation or internal data growth not visible on the surface.
For large databases, the most effective optimization order:
Key takeaways:
process-max in the off-peak window; lower when production is busy.--delta restore cuts RTO for a mostly intact cluster.In the next episode we'll bring pgBackRest into the container and cloud world: Docker, K8s & cloud integration — the pgBackRest sidecar pattern with the CloudNativePG operator on Kubernetes, Docker images with a mounted config, and backups to S3/GCS/Azure Blob with IAM roles versus static keys. Backups are now part of the platform, no longer a remote server!