Replication

PostgreSQL Streaming Replication, Step by Step

PG Monitoring Team May 18, 2026 10 min read

What Streaming Replication Is

Physical streaming replication ships the Write-Ahead Log (WAL) from a primary to one or more read-only standbys in near real time. The standby replays every change byte-for-byte, giving you a hot copy for failover and read scaling. It is block-level: the standby is an exact physical clone, same PostgreSQL major version, same architecture.

1. Configure the Primary

In postgresql.conf:

wal_level = replica
max_wal_senders = 10
max_replication_slots = 10
wal_keep_size = 1GB        # safety net if a slot is not used
hot_standby = on

Create a dedicated replication role and allow it in pg_hba.conf:

CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'secret';
# pg_hba.conf
host  replication  replicator  10.0.0.0/24  scram-sha-256

Reload: SELECT pg_reload_conf(); (or restart if you changed wal_level).

2. Create a Replication Slot

A slot guarantees the primary keeps WAL until the standby has consumed it — no more "requested WAL segment already removed" errors:

SELECT pg_create_physical_replication_slot('standby1');

3. Clone the Data Directory with pg_basebackup

On the standby host, take a base backup that also writes the connection settings:

pg_basebackup \
  -h primary.internal -U replicator \
  -D /var/lib/postgresql/16/main \
  -X stream -S standby1 -R -P

The flags that matter: -R writes standby.signal and the primary_conninfo automatically; -S standby1 binds the backup to the slot; -X stream streams WAL during the copy so the backup is consistent.

4. Start the Standby and Verify

Start PostgreSQL on the standby. It comes up read-only and begins streaming. Always verify — do not assume. On the primary:

SELECT client_addr, state, sent_lsn, replay_lsn,
       write_lag, flush_lag, replay_lag
FROM pg_stat_replication;

state = streaming and tiny lag values mean it is healthy. On the standby, SELECT pg_is_in_recovery(); returns t.

Synchronous vs Asynchronous

By default replication is asynchronous — the primary does not wait for the standby, so a crash can lose the last few transactions. For zero data loss, set synchronous_standby_names and the primary will wait for the standby to confirm each commit (at the cost of write latency). Most teams run async plus close lag monitoring.

The Three Lags That Matter

Notice pg_stat_replication reports write, flush and replay lag separately. They tell different stories: write lag points at the network, flush lag at standby disk I/O, replay lag at a long-running query on the standby blocking WAL replay. A single "lag: 12s" number hides which one is failing.

This decomposition is exactly what PG Monitoring tracks continuously, with a predictive risk score that warns you a standby is drifting toward failure hours before it falls over — instead of a snapshot you have to poll by hand.

Related Articles

Ready to experience better PostgreSQL monitoring?

Join thousands of teams who switched from traditional tools to PG Monitoring's AI-powered platform.

Talk to us