Skip to content

PostgreSQL Replication & HA — Section Overview

Contents:

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 walsender on a primary streams raw WAL to a walreceiver on a standby, which writes it to pg_wal for 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 (decodereorderbuffersnapbuild) that reassembles committed transactions from the physical WAL into an ordered stream of row changes, independent of the physical layout.
  • Output pluginspgoutput, 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 pgoutput stream and re-execute the changes locally.
  • Synchronous replication — the syncrep mechanism 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 backupBASE_BACKUP streams 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, and pg_combinebackup reconstructs 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 rmgr redo callbacks, 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_BACKUP command 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_basebackup and pg_combinebackup as programs (argument handling, output modes) are utilities (postgres-pg-basebackup.md); the server-side backup/ 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 same slot.c machinery 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) and snapbuild (reconstruct a catalog snapshot from the WAL) to turn byte-level records into row changes. pgoutput is 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.

Cross-referenced-first, so each doc’s dependencies are already in hand:

  1. 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.
  2. 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.
  3. postgres-logical-decoding.md — the decode/reorderbuffer/snapbuild core. The conceptual heart of the logical path; everything downstream is transport.
  4. postgres-pgoutput.md — the in-core output plugin. Short; read right after decoding since it is the serialization step.
  5. postgres-logical-replication-apply.md — the subscriber side (launcher, apply worker, tablesync). Closes the logical loop.
  6. postgres-synchronous-replication.md — the commit-wait overlay on the physical path. Read after wal-sender-receiver; it is orthogonal to logical.
  7. postgres-archiving-walsummary.md — archiver + WAL summarizer. Read before incremental backup, which consumes the summaries.
  8. postgres-backup-basebackup.md — the full physical backup mechanism.
  9. postgres-incremental-backup.md — builds on both the summarizer (7) and basebackup (8); read last.

Forward references — these module docs may not exist yet. One line each on what each will own.

Module docWhat it covers
postgres-wal-sender-receiver.mdPhysical 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.mdReplication 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.mdTurning 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.mdThe 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.mdThe 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.mdSynchronous 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.mdDraining 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.mdThe 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.mdIncremental 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.
  • txn-recovery (postgres-overview-txn-recovery.md) — the producer of the WAL this whole section consumes. postgres-xlog-wal.md owns WAL insertion and the LSN; postgres-recovery-redo.md owns 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. libpqwalreceiver rides 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 the B_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, and pg_receivewal.