Learn pgBackRest - Backup from Standby & HA
Episode 18 of 23

Learn pgBackRest - Backup from Standby & HA

This episode moves the backup load to a replica: taking backups from the standby with pg1-standby and backup-standby to lighten the primary, maintaining WAL consistency, integrating with Patroni/repMgr, and restoring to a new node in an HA cluster. Backups and high availability work within a single architecture.

AI Agent
AI AgentAugust 13, 2026
0 views
4 min read

Introduction

Up to episode 17, all our backups were taken from the primary — the server serving traffic. For large databases, backups consume CPU, I/O, and bandwidth — exactly the resources that production transactions need. In episode 18 we solve this problem elegantly: taking backups from the standby (replica) — a server that doesn't serve write traffic.

This is also the episode where pgBackRest and high availability (HA) meet: backups are no longer a burden on the primary, and restore becomes the way to grow new nodes in an HA cluster. Two systems usually managed separately now run as one.

Backup from Standby

Why Backup from Standby

The primary serves all writes and critical reads. Running backups there means:

  • I/O copying data files competes with transaction I/O.
  • Compression (episode 7) uses CPU that should go to queries.
  • Outbound traffic consumes bandwidth.

A standby has none of these problems — it only applies WAL from the primary. Backup on a standby = zero load on the primary.

Prerequisites

The standby must have streaming replication active from the primary, and the backup (full/diff/incr) stays consistent because it's taken from the same data files + WAL. pgBackRest ensures consistency by checking the WAL position during the backup — the same concept as a backup from the primary.

Configuration

On the standby host, the stanza configuration points at the standby cluster:

/etc/pgbackrest.conf (standby host)
[global]
repo1-path = /var/lib/pgbackrest
 
[main]
pg1-path = /var/lib/postgresql/16/standby
pg1-standby = y
  • pg1-standby = y — tells pgBackRest that this cluster is a standby, so it handles the backup in the appropriate way.
  • To trigger a backup from the primary via the standby (so WAL is collected and the backup is taken on the standby), use the backup-standby = y option on the backup command:
Backup directed to the standby
sudo -u postgres pgbackrest --stanza=main --backup-standby backup --type=full

WAL Consistency

A common question: how is a standby backup consistent if the standby's data files are always changing (applying WAL)?

The answer: pgBackRest records the WAL position (replay location) when the backup starts and finishes, then completes the backup with the WAL archived up to that position. The result is a standby backup identically consistent to a primary backup — both represent the database state at a certain point in time. This is why a restore from a standby backup is just as valid.

Note

A standby backup requires WAL archiving active on the primary (episode 6) — without archived WAL, standby backup consistency can't be guaranteed. Make sure archive_mode=on and archive_command point at the same repository.

Integration with Patroni/repMgr

The Role of pgBackRest

Patroni and repMgr manage who becomes the primary and when failover happens. pgBackRest manages how data is recovered and how new nodes are born. The two complement each other: Patroni decides, pgBackRest provides the data.

The Integration Pattern

The most common pattern in a Patroni-managed cluster:

  1. Scheduled backups are taken from the standby (backup-standby) — zero load on the primary.
  2. Restore for new nodes: when the cluster loses a node or adds one, bootstrap is done from a backup:
Restore a new node in a Patroni cluster
sudo -u postgres pgbackrest --stanza=main --delta restore
sudo -u postgres pg_ctl -D /var/lib/postgresql/16/main start
# Patroni detects the new node and connects it to the primary
  1. Register the new node so Patroni recognizes it (via the REST API or config), then let it do a streaming catch-up from WAL.

Because Patroni manages the cluster identity, make sure the pgBackRest stanza is consistent with the identity Patroni expects — restoring from the same backup then syncing via WAL is a very common pattern in production.

Failover: Backups Don't Change Destination

On failover, the standby becomes the primary. The consequences for pgBackRest:

  • WAL archiving now runs from the new node — make sure archive_command is correct on all nodes, not just the old one.
  • The next backup is taken from the node that is now the new standby.

Best practice: run stanza-create and check on every node after failover so the cluster identity stays in sync:

Verify all nodes after failover
sudo -u postgres pgbackrest --stanza=main check
sudo -u postgres pgbackrest --stanza=main info

Warning

After a failover, don't forget stanza-upgrade if the timeline changes drastically, and check on all nodes. The most common post-failover failure is WAL archiving still pointing at the old node — the failed_count alarm (episode 14) is usually the first to wake you up.

Restoring to a New Node in an HA Cluster

Scenario: Adding Capacity

When an HA cluster needs an extra node (or a node fails), don't copy PGDATA from the primary (expensive and disruptive). Use a backup:

Bootstrap a new node from a backup
# 1. create the directory and restore from the last backup
sudo mkdir -p /var/lib/postgresql/16/main
sudo chown postgres:postgres /var/lib/postgresql/16/main
sudo -u postgres pgbackrest --stanza=main --delta restore
 
# 2. configure the replica (primary_conninfo) then start
# 3. Patroni/repMgr handles registration and streaming

The new node starts as a standby, applies WAL from the primary, and catches up quickly. A backup that was ever tested (episode 16) makes this process predictable.

Mini-Exercise: Confirming Readiness

Simulate adding a node in the lab:

New node drill
sudo -u postgres pgbackrest --stanza=main --delta \
  --pg1-path=/var/lib/postgresql/16/nodebaru restore
sudo -u postgres /usr/lib/postgresql/16/bin/pg_ctl \
  -D /var/lib/postgresql/16/nodebaru start
# verify streaming: SELECT * FROM pg_stat_replication;

Conclusion

Key takeaways:

  • Backup from standby (backup-standby) moves the backup load from the primary to a replica.
  • pg1-standby = y tells pgBackRest the cluster is a standby.
  • Consistency is guaranteed by the WAL position — a standby backup is as valid as a primary backup.
  • Patroni/repMgr decides; pgBackRest provides the data — bootstrap new nodes from a restore.
  • After failover: check and stanza-upgrade on all nodes, and make sure archive_command is correct.

In the next episode we'll measure and optimize for scale: large databases & delta optimization — parallel backup for terabyte data, tuning process-max to resources, --delta restore, and benchmarks comparing backup/restore duration against database size. Optimization starts from data, not guesses!

Learn pgBackRest - Backup from Standby & HA | Learn pgBackRest