What you will learn

This is a PostgreSQL 15+ physical replication lab. Both servers use the same major version and compatible builds. Modern releases use standby.signal; old recovery.conf and standby_mode examples do not apply.

Before you begin

Prepare an empty standby data directory owned by the database service account, sufficient disk space, and private primary-to-standby connectivity. Configure a replication role, a narrow hostssl replication entry, TLS trust, wal_level=replica, and sufficient WAL senders/slots on the primary. Decide how replication slots and WAL retention will be monitored.

1. Inspect the primary

SHOW wal_level;
SHOW max_wal_senders;
SHOW max_replication_slots;
SELECT spcname, pg_tablespace_location(oid) FROM pg_tablespace;

Custom tablespaces require matching paths or pg_basebackup tablespace mappings. Confirm the standby will not overwrite a nonempty directory.

2. Take the base backup on the standby

pg_basebackup -d "host=host1.sample.com user=replicator sslmode=verify-full sslrootcert=/secure/ca.crt" \
  -D /srv/postgresql/standby -R -X stream -P

Run as the service account with protected credentials. -R creates standby.signal and writes connection settings; -X stream includes WAL while copying. This example does not create a slot. Configure adequate WAL retention or an explicitly monitored slot before leaving the standby disconnected for long periods.

3. Start and verify recovery

pg_ctl -D /srv/postgresql/standby -l /srv/postgresql/standby.log start
SELECT pg_is_in_recovery();
SELECT status, sender_host FROM pg_stat_wal_receiver;
SELECT pg_last_wal_receive_lsn(), pg_last_wal_replay_lsn();

Run these queries on the standby. Recovery should be true and WAL reception active. A standby can be running but still disconnected or far behind.

4. Prove a change reaches the standby

Create a small lab row on the primary, commit it, and query it on the standby. On the primary inspect pg_stat_replication for the expected connection and replay position. Rehearse reconnection after a brief network interruption without exhausting retained WAL.

Example output

The following is an illustrative, normalized lab result, not output captured from a live customer system. Your versions, addresses, timings, and row counts will differ.

pg_is_in_recovery
-------------------
 t
(1 row)

  status   |     sender_host
-----------+---------------------
 streaming | host1.sample.com
(1 row)

Recovery must stay true on the standby. A streaming receiver is the next check; then verify replay of a known committed row to prove the complete replication path.

Verify the result

The standby remains read-only, receives WAL from the intended primary, and replays the test transaction. Record WAL growth and lag thresholds. Recovery status alone does not prove that new transactions are arriving.

Troubleshooting

No WAL receiver commonly means credentials, pg_hba.conf, certificates, or routing are wrong. “Requested WAL segment has already been removed” requires a working archive path or a new base backup. Inactive replication slots can retain enough WAL to fill the primary disk.

Recovery and next steps

A failed initial copy can be restarted into a separately prepared empty directory after preserving diagnostic logs. Do not promote the standby merely to make it writable; promotion changes the topology and requires fencing the old primary.

References