Streaming Replication Basics
Physical streaming replication ships WAL records from a primary to one or more standbys in near real time. Standbys replay WAL and stay read-only until promoted.
Search across all documentation pages
Physical streaming replication ships WAL records from a primary to one or more standbys in near real time. Standbys replay WAL and stay read-only until promoted.
Quick setup checklist for a single async standby on PostgreSQL 18.4.
-- Primary: allow replication connections
ALTER SYSTEM SET wal_level = 'replica';
ALTER SYSTEM SET max_wal_senders = 10;
ALTER SYSTEM SET max_replication_slots = 10;
SELECT pg_reload_conf();
CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'change-me';# Standby: base backup from primary, then start in recovery
pg_basebackup -h primary.db.internal -D /var/lib/postgresql/18/main \
-U replicator -Fp -Xs -P -RWhen to reach for this: You need a hot standby for failover, read scaling, or backups without adding logical decoding overhead.
Primary postgresql.conf and pg_hba.conf, then standby creation:
# On primary host - pg_hba.conf snippet
# host replication replicator 10.0.0.0/8 scram-sha-256
# On standby host
sudo -u postgres pg_basebackup \
-h primary.db.internal \
-p 5432 \
-U replicator \
-D /var/lib/postgresql/18/main \
-Fp -Xs -P -R \
-C -S standby1_slot-- On primary: confirm standby is connected
SELECT application_name, client_addr, state, sync_state
FROM pg_stat_replication;What this demonstrates:
wal_level = replica enables physical replication without full logical decoding cost.pg_basebackup -R writes primary_conninfo and standby.signal for streaming recovery.-C -S standby1_slot creates a physical replication slot so WAL is retained for the new standby.hot_standby = on.standby.signal, run pg_ctl promote, or let Patroni 3.x elect a new leader.| Parameter | Typical value | Purpose |
|---|---|---|
wal_level | replica | Minimum for physical replication |
max_wal_senders | 10+ | Concurrent replication connections |
wal_keep_size | 1GB+ | Fallback if slots are missing |
hot_standby | on | Allow reads on standby |
| File | Role |
|---|---|
standby.signal | Tells PostgreSQL to stay in recovery |
postgresql.auto.conf | Holds primary_conninfo from -R |
recovery.signal | Used during PITR (not normal streaming) |
wal_level too low - minimal or insufficient setting blocks replication. Fix: Set replica or logical, restart if required.replication entry with scram-sha-256.pg_stat_replication.replay_lag and size standby I/O to match primary.| Alternative | Use When | Don't Use When |
|---|---|---|
| Logical replication | Major version upgrade, table subset, cross-DB | You need byte-identical clone and lowest replay overhead |
| pgBackRest / base backup only | DR without live replica | You need seconds-level RPO |
| Managed read replica (RDS, Cloud SQL) | Ops team is small | You need custom Patroni/etcd topology |
Yes. Physical replication replays all WAL, including DDL, indexes, and extensions on the same major version.
No, until promoted. Use logical replication or separate databases for bidirectional patterns.
PostgreSQL supports many; practical limits are network bandwidth, max_wal_senders, and primary CPU for WAL senders.
Use sslmode=verify-full in primary_conninfo and TLS on the primary. See SSL/TLS Configuration.
Physical streaming replication requires the same major version on primary and standby.
Stack versions: This page was written for PostgreSQL 18.4 (stable 18, maintenance 17), pgvector 0.8+, PgBouncer 1.x, Patroni 3.x, and PostGIS 3.5+.
Reviewed by Chris St. John·Last updated Jul 18, 2026