PITR Architecture
The PITR principle is compact; the engineering is not. WAL archiving must not stall production writes, object-storage backups need encryption, backup jobs must follow the primary after failover, shared repositories must isolate clusters, and large numbers of small objects can limit throughput.
Pigsty uses pgBackRest as its backup engine and ships production-oriented defaults for those concerns. This page describes the engine, repository abstraction, archive path, scheduler, and primary-aware execution model.
Backup Engine: pgBackRest
Pigsty uses pgBackRest for three responsibilities: create base backups with backup, receive WAL with archive-push, and restore data with restore plus archive-get.
Relevant capabilities include:
- Parallelism: backup, archive, and restore operations can use multiple processes.
- Backup chains: full, differential, incremental, and block incremental backups reduce repeated transfer and storage.
- Compression and encryption: zstd compression and AES-256-CBC repository encryption are built in.
- Repository backends: POSIX filesystems, S3-compatible services such as Silo and MinIO, Azure, GCS, and SFTP are supported by pgBackRest.
- Bundling: small files can be packed into larger repository objects, reducing object-storage overhead.
pgBackRest separates cluster histories using a stanza. Pigsty maps the stanza name directly to pg_cluster, allowing multiple clusters to share one storage service without sharing a backup identity:
Repository Abstraction
Two parameters define repository selection. pgbackrest_method chooses one repository name, and pgbackrest_repo is a dictionary of candidate definitions. Pigsty v4.5.0 renders only the selected pgbackrest_repo[pgbackrest_method] entry as pgBackRest repo1; listing both local and minio does not enable two active repositories.
The presets intentionally differ. local favors simplicity and fast local restore; it is unencrypted, unbundled, and retained by full-backup count. minio targets a remote Silo or compatible S3 repository, enabling encryption, bundles, block incremental backup, and time-based retention.
Rendering is mechanical: underscores in the chosen repository’s keys become hyphens and each key gets a repo1- prefix in /etc/pgbackrest/pgbackrest.conf. A custom cloud repository can therefore use pgBackRest options directly:
See Backup Repository for Silo, external S3-compatible storage, versioning, object locking, TLS, and credential details.
Archiving and Scheduling
When pgbackrest_enabled is true, as it is by default, the Patroni templates configure:
Base backups enter the system in two ways:
- Initial backup: after bootstrapping a top-level primary, Pigsty attempts a backup when
pgbackrest_init_backupis true. The task ignores backup failure and writes/etc/pgbackrest/initial.doneonly after success, so the marker means “completed,” not merely “attempted.” - Scheduled backup:
pg_crontabinstalls jobs in the database superuser’s crontab. Its role default is an empty list; standard example configurations usually add a daily 01:00 full backup.
pg-backup [full|diff|incr] is a small wrapper around pgbackrest backup. With no argument it requests an incremental backup, which pgBackRest promotes to a full backup if no usable full exists.
Backups Follow the Primary
pgBackRest and the same scheduled job are installed on every PostgreSQL node, but pg-backup checks /pg/bin/pg-role and only proceeds on the current primary. Replicas fail fast rather than writing a competing backup.
That design decouples the backup schedule from the HA topology:
- all members receive the same repository configuration and crontab;
- after failover, the new primary becomes eligible for subsequent backups and WAL archiving without rewriting the schedule;
- one current primary owns the authoritative write flow to a stanza.
With a non-local repository, Pigsty also adds pgBackRest after basebackup in Patroni’s create_replica_methods. Patroni tries basebackup first; if that method fails, it can restore a replica from the repository with pgbackrest --delta restore, shifting the copy load away from the primary.
Performance Defaults
The shipped pgBackRest template favors light production overhead and aggressive restore throughput:
| Setting | v4.5.0 behavior | Rationale |
|---|---|---|
| Compression | compress-type=zst |
Balance compression ratio and throughput |
| Backup/archive workers | One quarter of CPU, clamped to 2–4 | Limit competition with the database |
| Restore workers | All detected CPU, capped at 8 | Minimize restore time |
| Asynchronous archive | archive-async=y, spool under /pg/spool |
Batch transfer without synchronous object-store latency |
| Archive queue limit | archive-push-queue-max=4GiB |
Bound local spool growth |
| Fast backup start | start-fast=y |
Request an immediate checkpoint |
| Incremental restore | delta=y |
Reuse destination files that already match |
The 4 GiB queue is a safety tradeoff: if the repository remains unavailable and the queue exceeds the limit, pgBackRest can discard queued archive files. PostgreSQL continues running, but the WAL archive becomes incomplete and a new full backup is needed to establish a new recovery chain. See How PITR Works.
Observability
When both backup and exporter settings are enabled, pgbackrest_exporter runs on each PostgreSQL node and exposes metrics on port 9854. The monitoring stack uses those metrics for backup age, type, size, duration, and error visibility.
Useful diagnostic entry points include:
| Entry | Purpose |
|---|---|
pb info |
Shell helper for pgbackrest info using the configured stanza |
/pg/log/pgbackrest/ |
pgBackRest backup, archive, and restore logs |
| `pg-backup full | diff |
See Backup Administration for operational checks, then PITR Tradeoffs for policy design.