Implementing Streaming Replication
1. Understanding Streaming Replication
| Property | Detail |
|---|---|
| Granularity | Physical WAL (byte-for-byte) |
| Standby | Read-only (hot_standby) |
| Catch-up | WAL streaming, optional cascading |
| Failover | pg_promote / patroni / repmgr |
2. Configuring Primary Server
# postgresql.conf
wal_level = replica
max_wal_senders = 10
hot_standby = on
listen_addresses = '*'
3. Setting max_wal_senders
ALTER SYSTEM SET max_wal_senders = 16;
SELECT pg_reload_conf();
4. Setting wal_keep_size
# PG 13+
wal_keep_size = 1GB # minimum WAL retained on primary
5. Creating Replication User
CREATE ROLE repl WITH REPLICATION LOGIN PASSWORD 'replPass';
6. Configuring pg_hba.conf
# pg_hba.conf
host replication repl 10.0.0.0/24 scram-sha-256
7. Creating Base Backup
pg_basebackup -h primary -U repl -D /var/lib/postgresql/standby \
-Fp -Xs -P -R -S standby_slot
| Flag | Meaning |
|---|---|
| -Fp | Plain format |
| -Xs | Stream WAL alongside backup |
| -R | Write standby.signal + primary_conninfo |
| -S | Use replication slot |
8. Setting Up Standby Server
cd /var/lib/postgresql/standby
ls standby.signal # marker file present after -R
9. Configuring primary_conninfo
# postgresql.auto.conf (written by pg_basebackup -R)
primary_conninfo = 'host=primary port=5432 user=repl password=replPass application_name=standby1'
primary_slot_name = 'standby_slot'
10. Starting Standby Server
pg_ctl -D /var/lib/postgresql/standby start
psql -c "SELECT pg_is_in_recovery();" # → t
11. Monitoring Replication Lag
-- On primary
SELECT client_addr, state, sync_state,
pg_wal_lsn_diff(pg_current_wal_lsn(), sent_lsn) AS sent_lag,
pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) AS replay_lag
FROM pg_stat_replication;
-- On standby
SELECT now() - pg_last_xact_replay_timestamp() AS apply_lag;
12. Using Replication Slots
SELECT pg_create_physical_replication_slot('standby_slot');
SELECT * FROM pg_replication_slots;
13. Promoting Standby
SELECT pg_promote(wait := true, wait_seconds := 60);
-- or: pg_ctl promote -D /var/lib/postgresql/standby
14. Understanding Synchronous vs Asynchronous Replication
| Mode | COMMIT Returns When |
|---|---|
| async (default) | Primary WAL flushed locally |
| remote_write | Standby received (not fsynced) |
| on / remote_flush | Standby fsynced WAL |
| remote_apply | Standby applied (visible) |
15. Configuring synchronous_commit and synchronous_standby_names
synchronous_commit = on
synchronous_standby_names = 'FIRST 1 (standby1, standby2)'
# or: 'ANY 2 (s1, s2, s3)'
Warning: With no standby connected, sync replication BLOCKS commits. Always have a fallback or use ANY-quorum.