PostgreSQL Replication & HA — Section Overview
Contents:
- What this section covers
- The substrate: everything here consumes one WAL stream
- Reading order
- Detail-doc summaries
- Adjacent sections
What this section covers
Section titled “What this section covers”This subcategory covers everything PostgreSQL does with the WAL stream after it has been written and made durable: shipping it to other servers, turning it into logical row changes, making commits wait on remote acks, archiving it, summarizing it, and taking physical backups anchored to it. Concretely, the modules here own:
- Physical streaming replication — the
walsenderon a primary streams raw WAL to awalreceiveron a standby, which writes it topg_walfor the standby’s own startup process to replay. - Replication slots — the durable bookmark that pins the oldest WAL (and, for logical slots, the oldest catalog snapshot) a consumer still needs, so the primary does not recycle it prematurely. Includes failover-slot sync to standbys.
- Logical decoding — the machinery (
decode→reorderbuffer→snapbuild) that reassembles committed transactions from the physical WAL into an ordered stream of row changes, independent of the physical layout. - Output plugins —
pgoutput, the in-core plugin that serializes those decoded changes into the logical-replication wire protocol for publications. - Logical replication apply — the subscriber side: a launcher spawns
per-subscription apply workers (and table-sync workers for the initial copy)
that receive the
pgoutputstream and re-execute the changes locally. - Synchronous replication — the
syncrepmechanism that holds a committing backend until the configured standbys acknowledge the commit LSN. - Archiving and WAL summarization — the archiver (
pgarch) drains completed WAL segments to an archive for PITR; the WAL summarizer (walsummarizer) records which blocks changed, which is the substrate incremental backup consumes. - Base backup and incremental backup —
BASE_BACKUPstreams a physical snapshot of the data directory anchored to a start/stop WAL position; incremental backup uses the WAL summaries to copy only changed blocks, andpg_combinebackupreconstructs a full backup from the chain.
The boundaries, stated sharply. This section is deliberately the consumer side of the WAL. It does not cover:
- How WAL is produced, flushed, or replayed.
XLogInsert, the WAL-before-flush rule, the rmgrredocallbacks, and the standby’s startup process all belong to txn-recovery (postgres-xlog-wal.md,postgres-recovery-redo.md). This section reads the WAL those docs describe; replay on a physical standby is recovery, not replication. - The wire transport for replication commands. The
START_REPLICATION/BASE_BACKUPcommand grammar rides the same FE/BE protocol as normal queries; the protocol framing and authentication belong to client-protocol (postgres-wire-protocol.md,postgres-authentication.md).libpqwalreceiver(the dynamically loaded libpq transport the walreceiver uses) is named here but its libpq mechanics live there. - The historical arc. How replication evolved (file shipping → streaming
in 9.0 → sync/cascading in 9.1–9.2 → logical decoding in 9.4 → pub/sub in
10 → failover slots) is captured separately in
postgres-evolution-replication.md. This section describes the REL_18 current state only. - The client-side backup binaries’ UX.
pg_basebackupandpg_combinebackupas programs (argument handling, output modes) are utilities (postgres-pg-basebackup.md); the server-sidebackup/mechanism they drive is covered here.
The substrate: everything here consumes one WAL stream
Section titled “The substrate: everything here consumes one WAL stream”The organizing fact of this subcategory is that there is exactly one
durable event log — the WAL — and every module here is a different consumer
of it. The txn-recovery subcategory produces the stream; this section fans it
out into replication, logical decoding, archiving, and backup. The diagram
below names the postgres-*.md docs and shows which seam each one sits on.
flowchart TB
subgraph PROD["WAL producer (txn-recovery — NOT this section)"]
WAL["pg_wal segments<br/>postgres-xlog-wal.md"]
end
subgraph PHYS["physical path"]
WSND["walsender<br/>postgres-wal-sender-receiver.md"]
WRCV["walreceiver<br/>(standby, replays via recovery)"]
SYNC["synchronous wait<br/>postgres-synchronous-replication.md"]
end
subgraph SLOT["bookmark"]
SLOTS["replication slots<br/>postgres-replication-slots.md"]
end
subgraph LOGI["logical path"]
DEC["decode + reorderbuffer + snapbuild<br/>postgres-logical-decoding.md"]
PGO["pgoutput plugin<br/>postgres-pgoutput.md"]
APPLY["launcher + apply + tablesync<br/>postgres-logical-replication-apply.md"]
end
subgraph ARCH["archive + summarize"]
PGARCH["archiver + WAL summarizer<br/>postgres-archiving-walsummary.md"]
end
subgraph BKP["physical backup"]
BASE["basebackup<br/>postgres-backup-basebackup.md"]
INCR["incremental backup + combinebackup<br/>postgres-incremental-backup.md"]
end
WAL --> WSND
WSND --> WRCV
WSND --- SYNC
SLOTS -. "pin WAL + catalog xmin" .- WSND
WAL --> DEC
DEC --> PGO --> APPLY
SLOTS -. "pin WAL + catalog xmin" .- DEC
WAL --> PGARCH
WAL --> BASE
PGARCH -. "block summaries" .-> INCR
BASE --> INCR
Three structural points a reader should carry into the detail docs:
- Replication slots cut across both paths. A physical slot pins WAL so a
streaming standby that disconnects can resume; a logical slot pins WAL
and a catalog
xmin(via snapbuild) so decoding can still interpret old rows. The sameslot.cmachinery backs both — that is why slots are their own doc rather than folded into either path. - Logical decoding is layered on top of physical WAL, not beside it. The
decoder reads the same WAL segments the physical walsender ships; it adds
reorderbuffer(buffer changes until commit, then emit in commit order) andsnapbuild(reconstruct a catalog snapshot from the WAL) to turn byte-level records into row changes.pgoutputis just the serializer at the end of that chain. - Backup and archiving are WAL consumers too. A base backup is only consistent because it records a start/stop WAL position and the archive (or streamed WAL) covers the gap; incremental backup is a base backup that consults the WAL summarizer’s block-modification records to skip unchanged blocks. Neither is a separate durability mechanism — both are anchored to the same log.
Reading order
Section titled “Reading order”Cross-referenced-first, so each doc’s dependencies are already in hand:
postgres-wal-sender-receiver.md— the physical streaming pair. Read first; it establishes the producer/consumer framing and the walsender/walreceiver handshake that the rest of the section assumes.postgres-replication-slots.md— the bookmark mechanism. Both the physical path and the logical path depend on it, so read it before either logical doc.postgres-logical-decoding.md— the decode/reorderbuffer/snapbuild core. The conceptual heart of the logical path; everything downstream is transport.postgres-pgoutput.md— the in-core output plugin. Short; read right after decoding since it is the serialization step.postgres-logical-replication-apply.md— the subscriber side (launcher, apply worker, tablesync). Closes the logical loop.postgres-synchronous-replication.md— the commit-wait overlay on the physical path. Read after wal-sender-receiver; it is orthogonal to logical.postgres-archiving-walsummary.md— archiver + WAL summarizer. Read before incremental backup, which consumes the summaries.postgres-backup-basebackup.md— the full physical backup mechanism.postgres-incremental-backup.md— builds on both the summarizer (7) and basebackup (8); read last.
Detail-doc summaries
Section titled “Detail-doc summaries”Forward references — these module docs may not exist yet. One line each on what each will own.
| Module doc | What it covers |
|---|---|
postgres-wal-sender-receiver.md | Physical streaming replication: the walsender command loop (exec_replication_command, StartReplication, WalSndLoop, XLogSendPhysical) and the walreceiver (WalReceiverMain, XLogWalRcvProcessMsg/XLogWalRcvWrite) that writes streamed WAL to pg_wal, plus the WalRcvData/WalSndCtl shared-memory IPC and the libpqwalreceiver transport seam. |
postgres-replication-slots.md | Replication slots as the durable WAL/catalog bookmark: physical vs logical slots, restart_lsn/catalog_xmin, slot persistence and advance (slot.c, slotfuncs.c), and failover-slot synchronization to standbys (slotsync.c). |
postgres-logical-decoding.md | Turning physical WAL into ordered row changes: the rmgr decode callbacks (decode.c), transaction reassembly and spill-to-disk (reorderbuffer.c), historic catalog-snapshot reconstruction (snapbuild.c), and the LogicalDecodingContext that ties them together (logical.c). |
postgres-logical-replication-apply.md | The subscriber side: the logical-replication launcher spawning per-subscription workers (launcher.c), the apply worker re-executing changes (worker.c, plus parallel apply in applyparallelworker.c), initial table synchronization (tablesync.c), and conflict handling (conflict.c). |
postgres-pgoutput.md | The in-core output plugin: how pgoutput.c implements the output-plugin callbacks to serialize decoded changes into the logical-replication wire protocol, publication filtering, row/column filters, and streaming of in-progress transactions. |
postgres-synchronous-replication.md | Synchronous commit: how syncrep.c parks a committing backend on SyncRepWaitForLSN until the configured quorum/priority set of standbys acks the commit LSN, the synchronous_standby_names grammar, and the interaction with synchronous_commit levels. |
postgres-archiving-walsummary.md | Draining and summarizing WAL: the archiver process invoking the archive command/library (pgarch.c, xlogarchive.c) for PITR, and the WAL summarizer (walsummarizer.c) producing block-modification summaries (walsummary.c) consumed by incremental backup. |
postgres-backup-basebackup.md | The server-side physical backup: the BASE_BACKUP replication command, the sink/target abstraction and compression pipeline (basebackup.c, basebackup_copy.c, basebackup_sink.c, basebackup_* codecs), the backup manifest, and start/stop-backup WAL anchoring. |
postgres-incremental-backup.md | Incremental backup: how basebackup_incremental.c consults WAL summaries to copy only changed blocks since a prior backup, the incremental manifest, and pg_combinebackup reconstructing a full backup from an incremental chain. |
Adjacent sections
Section titled “Adjacent sections”- txn-recovery (
postgres-overview-txn-recovery.md) — the producer of the WAL this whole section consumes.postgres-xlog-wal.mdowns WAL insertion and the LSN;postgres-recovery-redo.mdowns replay (which is what a physical standby’s startup process does with streamed WAL). The seam: txn-recovery writes and replays WAL; replication-ha ships, decodes, archives, and backs it up. - client-protocol (
postgres-overview-client-protocol.md) — the FE/BE wire protocol that carries replication commands (START_REPLICATION,BASE_BACKUP) and authenticates replication connections.libpqwalreceiverrides this transport. The seam: client-protocol owns the framing and auth; replication-ha owns what the framed commands do. - server-architecture (
postgres-overview-server-architecture.md) — owns the process roles this section’s actors run as (B_WAL_SENDER,B_WAL_RECEIVER,B_WAL_SUMMARIZER,B_ARCHIVER,B_SLOTSYNC_WORKER, and theB_BG_WORKERs that apply logical changes) and the shared-memory/latch IPC they coordinate through. - monitoring-stats (
postgres-overview-monitoring-stats.md) — surfaces replication progress (pg_stat_replication,pg_replication_slots,pg_stat_subscription) and the wait events these processes report while parked. - utilities (
postgres-overview-utilities.md) — the client binaries that drive this section’s server mechanisms:pg_basebackup,pg_combinebackup, andpg_receivewal.