Implementing Streaming Replication

1. Understanding Streaming Replication

PropertyDetail
GranularityPhysical WAL (byte-for-byte)
StandbyRead-only (hot_standby)
Catch-upWAL streaming, optional cascading
Failoverpg_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
FlagMeaning
-FpPlain format
-XsStream WAL alongside backup
-RWrite standby.signal + primary_conninfo
-SUse 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

ModeCOMMIT Returns When
async (default)Primary WAL flushed locally
remote_writeStandby received (not fsynced)
on / remote_flushStandby fsynced WAL
remote_applyStandby 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.