Recommended Free Tools
PostgreSQL physical streaming replication copies WAL (write-ahead log) records from a writable primary server to a read-only standby. On Ubuntu, the reliable sequence is to prepare two compatible hosts, configure replication on the primary, create a consistent standby with pg_basebackup, start streaming, then monitor lag and WAL retention. Streaming is asynchronous unless you explicitly configure synchronous commit behavior, so an unplanned primary failure can lose commits that had not reached the standby.
Need a server to try this on? Antihost offers Linux VPS plans with NVMe storage, full root access and a 14-day free trial.
This guide uses current PostgreSQL terms. The title’s “master-slave” wording refers to the same primary-and-standby arrangement, not to a separate PostgreSQL feature.
As an Amazon Associate I earn from qualifying purchases.
What PostgreSQL replication does—and what it does not do
Physical streaming replication sends a primary’s WAL records to one or more standbys. The standby replays those records against a copy of the entire cluster, making it suitable for disaster recovery, read-only workloads, and a manually operated failover. It is physical replication: it copies database changes at the storage/WAL level rather than selecting individual tables.
- The primary accepts writes.
- A standby receives and replays WAL, normally remaining in recovery mode.
- Replication does not automatically elect a new leader, redirect clients, fence an old primary, prevent split brain, or provide historical backups.
- Keep independent backups and test point-in-time recovery; a promoted or damaged standby is not a substitute for them.
Prerequisites for two Ubuntu hosts
Use a primary and a standby with network reachability on PostgreSQL’s listening port (normally 5432), synchronized clocks, matching PostgreSQL major versions, and enough disk for the base copy plus retained WAL. Confirm the actual package, service unit, configuration directory, and data directory before editing anything. Ubuntu package layouts commonly resemble /etc/postgresql/<major>/main/ and /var/lib/postgresql/<major>/main/, but the installed major version determines the path.
#1 Best Overall
- Give each host a stable address or DNS name and restrict firewall access to the standby’s address.
- Use a protected administrative path (console or SSH) so a configuration error does not lock you out.
- Record the primary address, standby address, PostgreSQL major version, service name, data directory, and intended slot name.
- Ensure the standby data directory can be replaced;
pg_basebackupcreates a complete cluster copy.
Find the installed version and units instead of assuming them:
psql --version
systemctl list-units --type=service 'postgresql*'
pg_lsclusters
Configure the primary for physical replication
Set WAL level and sender capacity
Edit the primary’s active postgresql.conf (or use an equivalent supported configuration method). Set a WAL level suitable for physical replication and reserve enough WAL sender processes:
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →wal_level = replica
max_wal_senders = 10
PostgreSQL documents a default max_wal_senders value of 10. The value must be greater than the number of standbys and concurrent base-backup connections you expect. A value of zero disables replication. If you run several standbys or backups, increase it accordingly rather than copying the default blindly.
Create a dedicated replication role
Connect locally as the PostgreSQL administrative account and create a login used only for replication. Use a long, unique secret and protect it as you would any other database credential:
sudo -u postgres psql
CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'replace-with-a-long-random-secret';
Do not use the general application owner for this connection. A dedicated role makes auditing, rotation, and access removal clearer.
Allow only the standby in pg_hba.conf
Add a narrow rule to the primary’s active pg_hba.conf. Replace STANDBY_IP with the standby’s address and choose an authentication method supported by your installation:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
host replication replicator STANDBY_IP/32 scram-sha-256
The special replication database field applies to replication protocol connections. Do not use a broad network range when one standby address is sufficient. Also restrict the host firewall to PostgreSQL’s port and the standby address.
Reload or restart correctly
Authentication rules can normally be applied with a reload. Parameters that require startup, such as some WAL settings, require a restart. Check the parameter’s context in the installed PostgreSQL documentation and then use the package’s actual service unit:
sudo systemctl reload postgresql
sudo systemctl restart postgresql
On installations with cluster-specific units, the command may instead be expressed through the cluster wrapper, for example sudo pg_ctlcluster <major> main restart. Verify the result with systemctl status and the PostgreSQL log before proceeding.
Decide whether to use a physical replication slot
A slot records how far a standby has consumed WAL. It prevents the primary from removing WAL that the slot still requires, which lets a temporarily disconnected standby catch up without an immediate re-seed. The cost is disk risk: an abandoned or permanently broken slot can retain WAL until the pg_wal filesystem fills.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problemsCreate a physical slot on the primary if your operating procedure includes slot monitoring:
sudo -u postgres psql -c "SELECT pg_create_physical_replication_slot('standby1');"
If you do not use a slot, configure WAL archiving and a recovery procedure that can supply missing segments. Without either a usable archive or sufficient retained WAL, a standby that falls too far behind must be initialized again from a fresh base backup.
| Choice | Disconnected-standby recovery | Storage risk | Operational requirement |
|---|---|---|---|
| Physical replication slot | Retains required WAL on the primary until the standby advances. | An inactive slot can consume all available pg_wal space. |
Monitor slot activity, restart-LSN age, and free disk; consider max_slot_wal_keep_size as a limit. |
| WAL archiving | Allows a lagging standby to retrieve archived segments when the archive is healthy. | Archive storage and retention must be sized and maintained. | Monitor archive success, retrieval, retention, and restore procedures. |
Initialize the standby with pg_basebackup
pg_basebackup takes a consistent copy of the entire running cluster over the replication protocol. It is the normal starting point for a physical streaming standby.
Stop the standby and protect the target directory
On the standby, stop PostgreSQL and confirm that no process is using the target data directory. Move an old directory aside or remove it only after verifying that it contains nothing you need:
sudo systemctl stop postgresql
sudo mv /var/lib/postgresql/<major>/main /var/lib/postgresql/<major>/main.before-reseed
sudo install -d -o postgres -g postgres -m 700 /var/lib/postgresql/<major>/main
Use the real data directory reported by pg_lsclusters; never delete a directory based solely on an assumed version.
Run the base backup
Run this from the standby, connecting to the primary. The -R option writes standby connection settings and creates the startup marker needed by current PostgreSQL versions. The -X stream option streams required WAL during the backup:
sudo -u postgres pg_basebackup
-h PRIMARY_HOST -p 5432 -U replicator
-D /var/lib/postgresql/<major>/main
-Fp -P -R -X stream -S standby1
The role must pass the primary’s pg_hba.conf rule. If you did not create a slot in advance, you can have pg_basebackup create one with -C -S standby1, provided the role has the required permission. Do not combine that creation step with an already existing slot of the same name.
For unattended operation, avoid putting a reusable password in a command line or world-readable file. Use a .pgpass file owned by postgres with mode 600, or an equivalent secret manager. A matching entry contains the primary host, port, replication database field, role, and password.
Check ownership and generated files
After the backup finishes, verify that the copied directory and its contents are owned by the PostgreSQL operating-system user. Confirm that the directory contains standby.signal and that postgresql.auto.conf or the chosen configuration contains the generated primary_conninfo. If you use a slot, ensure the name is exactly standby1 (or your chosen name) in the standby configuration.
Configure the standby connection and startup behavior
Set or review the following settings in the copied data directory. pg_basebackup -R usually writes the connection information, but inspect it rather than assuming it is correct:
primary_conninfo = 'host=PRIMARY_HOST port=5432 user=replicator application_name=standby1'
primary_slot_name = 'standby1'
hot_standby = on
Keep the password out of broadly readable configuration files when possible; use the protected .pgpass entry described above. hot_standby = on allows read-only queries while recovery replays WAL. Reads can be behind the primary, and recovery conflicts can cancel long-running queries, so do not treat the standby as a current, writable copy.
Start the cluster with the correct Ubuntu service command:
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchsudo systemctl start postgresql
sudo systemctl status postgresql
If your installation exposes a versioned unit, use that unit instead. The standby should remain in recovery mode; it must not start as an independent writable cluster.
Verify that streaming is active
Check the primary’s sender view
On the primary, inspect pg_stat_replication:
sudo -u postgres psql -x -c "SELECT application_name, client_addr, state, sync_state, sent_lsn, write_lsn, flush_lsn, replay_lsn, reply_time FROM pg_stat_replication;"
Find the standby’s row and confirm state is streaming. The address, application name, and LSN columns should identify the expected host. sync_state will normally be async unless you have configured it as a synchronous candidate.
Check the standby receiver and recovery state
On the standby, run:
sudo -u postgres psql -c "SELECT pg_is_in_recovery();"
sudo -u postgres psql -x -c "SELECT status, receive_start_lsn, received_lsn, latest_end_lsn, latest_end_time, conninfo FROM pg_stat_wal_receiver;"
sudo -u postgres psql -c "SELECT pg_last_wal_receive_lsn(), pg_last_wal_replay_lsn(), pg_last_xact_replay_timestamp();"
pg_is_in_recovery() should return true while the server is a standby. A connected receiver and advancing LSNs show that WAL is arriving and being replayed.
Perform a harmless end-to-end test
Create a temporary test table or row on the primary, wait for replay, and query it read-only on the standby. Remove the test object afterward. This catches incorrect hostnames, authentication, firewall rules, data-directory mistakes, and a standby that is receiving WAL but not replaying it.
Choose asynchronous or synchronous replication
Streaming replication is asynchronous by default. A primary can report a commit before the standby has received or replayed its WAL. If the primary fails at that point, the standby may not contain those commits. The possible loss is not a universal number of seconds: it depends on network, storage, workload, and the exact receive position at the failure.
| Axis | Asynchronous | Synchronous |
|---|---|---|
| Commit latency | Primary commits without waiting for a standby acknowledgement; usually lower latency. | Required acknowledgements add network and standby durability latency. |
| Primary failure | Transactions not yet replicated can be lost after promotion. | Configured synchronous acknowledgements provide a stronger durability boundary, subject to the selected policy and connected standbys. |
| Standby unavailable | Writes continue; lag and eventual data loss exposure grow. | Writes can wait or fail when the required synchronous standby is unavailable. |
| Read staleness | Standby reads can lag the primary. | Commit acknowledgement reduces acknowledged-commit exposure, but replay and query routing still need monitoring. |
| Operational complexity | Lower; you must monitor lag and define an explicit loss boundary. | Higher; configure names, quorum or priority behavior, and availability procedures. |
| Best fit | Workloads prioritizing write availability and accepting a bounded, monitored loss window. | Workloads where acknowledged commits need stronger protection and added latency is acceptable. |
Configure synchronous commit deliberately
Use synchronous_standby_names on the primary to identify eligible standby names, matching the standby’s application_name. PostgreSQL considers synchronous standbys to be the names in that list that are currently connected and streaming in real time. Choose an appropriate synchronous_commit policy for the sessions or cluster. Test both normal operation and the behavior when the required standby is stopped; the durability gain is purchased with reduced write availability when the acknowledgement cannot arrive.
Best Value
Monitor lag, WAL retention, and disk space
Monitoring is part of the deployment, not an optional refinement. On the primary, collect connection state, LSN positions, and slot status at an interval appropriate to your recovery objective:
sudo -u postgres psql -x -c "SELECT application_name, client_addr, state, sync_state, pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn)) AS replay_bytes_behind FROM pg_stat_replication;"
sudo -u postgres psql -x -c "SELECT slot_name, slot_type, active, restart_lsn, wal_status, safe_wal_size FROM pg_replication_slots;"
df -h /var/lib/postgresql/<major>/main
Column availability can vary by major version, so adapt the query to the installed release. Alert on a disconnected receiver, increasing replay delay, failed WAL archiving, an inactive slot whose restart position continues to age, and low free space on the filesystem containing pg_wal. There is no universal safe lag threshold; set one from the amount of data loss and recovery time your workload can tolerate.
What to do when a standby falls behind
- Check the standby receiver log, DNS or address, firewall, credentials, and PostgreSQL service status.
- Check whether the primary still retains the required WAL through the configured slot or archive.
- Inspect slot growth and free space before restarting anything; do not allow an abandoned slot to fill the primary’s disk.
- If required WAL has been removed and no archive can supply it, stop the standby and seed it again with a new
pg_basebackup. - After recovery, verify
state = 'streaming', advancing receive/replay LSNs, and a successful test row.
Troubleshoot a standby that is not streaming
No row in pg_stat_replication
- Confirm the standby service is running and the data directory contains
standby.signal. - Check
primary_conninfofor the correct host, port, user, and application name. - Test network reachability to the primary’s PostgreSQL port from the standby.
- Read the standby log for authentication failures, name-resolution errors, or connection refusal.
- Confirm the primary’s
pg_hba.confrule matches the standby’s actual source address and was reloaded.
Authentication or permission errors
Verify that the role has LOGIN and REPLICATION, the password source is readable only by the PostgreSQL operating-system user, and the rule uses the replication database field. A changed password requires updating the protected credential on the standby.
The standby connects but WAL does not advance
Check the primary’s sender capacity, slot status, disk space, and whether the standby is replaying or blocked by recovery conflicts. Compare sent, received, flushed, and replayed LSNs rather than looking only at a connection flag. If the slot’s retained WAL is consuming the filesystem, pause and correct the retention problem before the disk reaches zero free space.
Base backup fails
Ensure the target directory is empty or moved aside, owned by postgres, and large enough for the whole cluster. Confirm the replication rule, role password, primary reachability, and available WAL sender capacity. A base backup that completes into the wrong directory will not become the active standby, so verify the cluster’s configured data path before starting the service.
Plan promotion and rejoining before an outage
Replication supplies a copy, not an automatic failover system. Write and test a runbook that names the person or automation authorized to promote, the client-routing change, the fencing method for the old primary, and the procedure for rebuilding a standby.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Manual promotion boundary
After confirming that the primary is unavailable and fencing it so it cannot accept writes, promote the chosen standby using the supported PostgreSQL method, such as:
sudo -u postgres pg_ctlcluster <major> main promote
You can also use SELECT pg_promote(); while connected locally. Verify that pg_is_in_recovery() is false, then redirect applications to the promoted server. The exact client-routing mechanism is deployment-specific; replication alone does not change connection strings or DNS.
Rebuild the old primary safely
Never allow the old primary to reappear as a writable peer while the new primary is accepting writes. Fence it, preserve any required evidence, and re-seed it as a standby from a fresh consistent base backup (or use a separately validated rejoin procedure). Recheck roles, slots, credentials, firewall rules, and monitoring after the rebuild.
Quick Recap
Operational checklist
- Primary and standby run compatible PostgreSQL major versions and have synchronized clocks.
wal_levelsupports physical replication andmax_wal_senderscovers standbys plus base backups.- A dedicated replication role and narrowly scoped
pg_hba.confrule are in place. - The standby was initialized from a consistent
pg_basebackupand uses protected credentials. primary_conninfo,standby.signal, and (when selected)primary_slot_nameare correct.- The primary shows the standby as
streaming; receiver and replay positions advance on the standby. - Your asynchronous loss boundary or synchronous availability policy is documented.
- Slots, archives, WAL growth, lag, receiver disconnects, and disk capacity generate alerts.
- Independent backups, point-in-time recovery, promotion, client routing, fencing, and standby rebuilds are tested.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
Free tools Windows power users keep installed
One-click scans. No signup required.




