Skip to main content
RunBook Academy

PostgreSQLXIV · Replication, Slots and Read ReplicasReplication

Synchronous replication and the trade-off it makes

Advanced⏱ ~35 minpgbenchpsql

What you'll learn

  • Distinguish the synchronous_commit levels by the guarantee each buys
  • Configure synchronous_standby_names, including quorum forms
  • Recognise and prevent the availability failure synchronous replication introduces
  • Decide whether synchronous replication is warranted

Prerequisites

Verified against PostgreSQL 18.x · PostgreSQL (comparison targets) 17.11, 16.15 · PostgreSQL (support calendar) 18, 17, 16, 15, 14 supported · pgBackRest 2.59.1 · PgBouncer 1.25.2 · Patroni 4.1.5 · Ubuntu (host baseline) 26.04 LTS · 2026-08-27

Not yet marked complete on this device.

Asynchronous replication means a commit is durable on one machine. If that machine’s storage is destroyed between the commit and the standby receiving it, the transaction is lost while the client believes it succeeded.

Synchronous replication closes that window, and the price is not subtle.

The levels

synchronous_commit has five values. Two concern only local durability and were covered in lesson XII-01; three concern the standby.

ValueCommit returns whenSurvives
offWAL is in the bufferNothing. Crash loses recent commits
localWAL is flushed locallyPrimary crash. Not primary loss
remote_writeStandby’s OS has itStandby process crash. Not standby host loss
onStandby has fsynced itLoss of either machine
remote_applyStandby has replayed itSame as on, plus read-your-writes

on is the default, and on a cluster with no synchronous_standby_names it means local flush only. Setting synchronous_commit = on does not make replication synchronous. Two settings are required.

The measured cost

Read-only / Safefour levels on the same pair, same standby, 20-second runs
$ pgbench -U postgres -c 8 -j 4 -T 20 postgres
  setting            tps      latency avg    relative
-----------------  -------  -----------    --------
local              1624     4.926 ms       100%
remote_write       1625     4.923 ms       100%
on (remote flush)  1474     5.428 ms        91%
remote_apply       1462     5.470 ms        90%

(asynchronous baseline, synchronous_standby_names empty:
 1618 tps / 4.940 ms — indistinguishable from 'local')

Configuring it

# on the primary
synchronous_standby_names = 'standby1'
synchronous_commit = on

The name matches the standby’s application_name, which comes from primary_conninfo. Set it explicitly:

primary_conninfo = '... application_name=standby1'

Without it, the default is walreceiver for every standby, and you cannot distinguish them.

Read-only / Safeconfirming a standby is actually synchronous
$ SELECT application_name, sync_state, sync_priority FROM pg_stat_replication;
 application_name | sync_state
------------------+------------
walreceiver      | sync

sync_state is the only trustworthy confirmation. Anything else is belief.

Quorum forms

synchronous_standby_names = 'standby1'                  # exactly this one
synchronous_standby_names = 'FIRST 1 (s1, s2)'          # s1 preferred, s2 fallback
synchronous_standby_names = 'ANY 1 (s1, s2, s3)'        # any one of three
synchronous_standby_names = 'ANY 2 (s1, s2, s3)'        # any two of three

ANY 1 (s1, s2) is the form that makes synchronous replication survivable in practice, and the reason is the next section.

When it is warranted

Synchronous replication is right when losing an acknowledged transaction is worse than being unavailable: payments, ledgers, regulatory records, anything where “we told them it succeeded and it did not” is the worse outcome.

It is wrong when availability matters more than the last few transactions, which is most systems. A well-monitored asynchronous standby with lag measured in milliseconds — as measured in lesson XIV-04, 2.5 ms at 1,623 tps — has an RPO of milliseconds without the availability coupling.

There is a middle path that is often the right answer: synchronous_commit is a per-transaction setting.

-- most work: asynchronous, fast
SET synchronous_commit = local;

-- the transactions that must not be lost
BEGIN;
SET LOCAL synchronous_commit = remote_apply;
INSERT INTO payments ...;
COMMIT;

The cost is paid only by the transactions that need it. On a system where 1% of commits are financially significant, that is a 1% cost instead of a 9% one.

What to take from this

  • synchronous_commit = on alone changes nothing. synchronous_standby_names is what makes replication synchronous.
  • remote_write / on / remote_apply buy standby-OS, standby-disk and standby-visibility guarantees respectively.
  • Measured on a loopback pair: 9% throughput cost for remote flush. Over a real network the round trip dominates. Measure yours.
  • One synchronous standby makes you less available than none. Use ANY 1 (s1, s2).
  • Alert on sync_state, and rehearse dropping to asynchronous as an explicit decision.
  • synchronous_commit is per-transaction. Pay the cost only where it buys something.

Cross-course references

  • Linux for Production Sysadmins — Part LII (High availability fundamentals) and Part LIII (Quorum and split brain) cover the same trade between durability and availability, and why a quorum of one is a single point of failure wearing a quorum’s clothes.
  • Observability for Production Sysadmins — Part LIX (Database observability) covers alerting on sync_state, because a cluster silently demoted to asynchronous reports nothing.

Quiz

Knowledge check · 6 questions

  1. Q1. A team sets synchronous_commit = on and reports that replication is now synchronous. What have they actually changed?

  2. Q2. With synchronous_standby_names = 'standby1' and that standby stopped for maintenance, what does the primary do?

  3. Q3. During a synchronous stall an operator cancels waiting backends one at a time. Why is that the wrong approach?

  4. Q4. Which are sound responses to a synchronous replication stall? Select all that apply.

  5. Q5. synchronous_commit can be set per transaction, so only the transactions that need the guarantee pay for it.

  6. Q6. The benchmark in this lesson showed a 9% throughput cost for remote flush. Why must that number not be quoted as the cost of synchronous replication?

Passing score: 75%. Answers are checked in this browser.