appprimarydownstandbyprimaryreportsreceived0replayed0id name year1 Dune 19652 Coraline 20023 Piranesi 20204 Circe 20185 Wonder 20121INSERT 3 Piranesi2COMMIT3INSERT 4 Circe4COMMIT5INSERT 5 Wonder6COMMITid name year1 Dune 19652 Coraline 20023 Piranesi 20204 Circe 20185 Wonder 20123WALrecackINSERTwrites
Back row: the apps and the two servers (primary and standby)Front: books on each server, the primary's WAL, the standby's received and replayed countersMovers: inserts, replies, the streamed WAL, the replayed record and the 'writes' markerAt the back: the library app that writes, the primary, the standby and the reports app that reads. In front: the books table on each server and the primary's write-ahead log, with how far the standby has received and replayed it. Every change on the primary becomes WAL records; they stream to the standby, which replays them into its own copy. The standby answers reads, refuses writes, can lag behind, and is promoted to primary when the primary fails. The figure numbers WAL records 1, 2, 3 from the base backup. A real server marks each place in the log with a log sequence number (LSN), a byte position written like 0/3000110; pg_waldump lists the records (Heap INSERT, Transaction COMMIT).

Shipping the log

  1. One database server is a single point of failure: if it dies, every app stops. Replication keeps a live copy on a second server. The primary takes every write; the standby, also called a replica, follows it.

Using the copy

Lag, sync and failover

What happens

;; step 1/10 · why
primary   takes every write (INSERT, UPDATE, DELETE)
standby   a second server that follows it
          (also called a replica or secondary)

the standby starts as a full copy, a base backup:
  pg_basebackup -h primary -U repl -D /srv/standby -R
  -R writes standby.signal and primary_conninfo,
     so it starts up as a standby of that primary

give the standby a name, in its postgresql.conf:
  cluster_name = 'standby1'
  (its WAL receiver connects with this name)

both now hold books: Dune, Coraline

The figure numbers WAL records 1, 2, 3 from the base backup. A real server marks each place in the log with a log sequence number (LSN), a byte position written like 0/3000110; pg_waldump lists the records (Heap INSERT, Transaction COMMIT). With asynchronous replication a failover can lose the last commits the primary had confirmed but not yet streamed. Synchronous commit closes that gap, but only for the standbys it waits for.