Guide contents

Lesson 27 of 30

Replication and CAP

Replication keeps copies of the same data on several servers to survive failures, serve more reads, and place data near users. See also database replication.

Example 1: leader-follower replication

One leader (primary) accepts writes and streams changes to followers (replicas, standbys), which serve reads.

flowchart LR
    C["Clients (writes)"] --> L["Leader"]
    L -->|"WAL / binlog stream"| F1["Follower 1"]
    L -->|"WAL / binlog stream"| F2["Follower 2"]
    R["Clients (reads)"] --> F1
    R --> F2
Term PostgreSQL MySQL
Change stream WAL Binary log (binlog)
Leader Primary Source (primary)
Follower Standby (hot standby allows reads) Replica

Example 2: synchronous, asynchronous, semi-synchronous

The commit returns to the client after different events depending on the mode.

Mode Commit returns after Data loss on leader crash Write latency
Asynchronous Leader wrote locally Possible (recent commits not yet sent) Lowest
Semi-synchronous At least one follower received the change Very unlikely Medium
Synchronous Follower(s) confirmed (received, flushed, or applied) None for the confirmed level Highest; a slow follower slows writes

PostgreSQL controls this with synchronous_commit (off, local, remote_write, on, remote_apply) and synchronous_standby_names. MySQL has semi-synchronous replication as a plugin and Group Replication for consensus-based commit.

SQL
SELECT name, boot_val, short_desc
FROM pg_settings
WHERE name IN ('synchronous_commit', 'wal_level', 'max_wal_senders', 'hot_standby')
ORDER BY name;
Output
        name        | boot_val |                               short_desc                                
--------------------+----------+-------------------------------------------------------------------------
 hot_standby        | on       | Allows connections and queries during recovery.
 max_wal_senders    | 10       | Sets the maximum number of simultaneously running WAL sender processes.
 synchronous_commit | on       | Sets the current transaction's synchronization level.
 wal_level          | replica  | Sets the level of information written to the WAL.
(4 rows)

Example 3: replication lag and read-your-writes

Asynchronous followers apply changes after the leader. A read from a follower right after a write can return old data.

sequenceDiagram
    participant U as User
    participant L as Leader
    participant F as Follower
    U->>L: UPDATE profile
    L-->>U: OK
    L-->>F: replicate (delayed)
    U->>F: SELECT profile
    F-->>U: old value
Anomaly Meaning Fix
Read-your-writes violation User does not see their own write Read own recent data from the leader, or track the write's LSN and wait for a follower to reach it
Monotonic reads violation User sees newer data, then older data from another follower Pin a user to one follower
Consistent prefix violation Effects seen before causes Keep related writes on one partition or use causal ordering

Lag in bytes is the difference between WAL positions (pg_lsn values subtract to a byte count):

SQL
SELECT '0/3000128'::pg_lsn - '0/3000000'::pg_lsn AS lag_bytes;
Output
 lag_bytes 
-----------
       296
(1 row)

Example 4: monitoring replication in PostgreSQL

On a primary, pg_stat_replication has one row per connected standby. This server has no standby, so the view is empty; the column list shows what it reports.

SQL
SELECT count(*) AS connected_standbys FROM pg_stat_replication;
Output
 connected_standbys 
--------------------
                  0
(1 row)
SQL
SELECT column_name
FROM information_schema.columns
WHERE table_name = 'pg_stat_replication'
  AND column_name IN ('client_addr', 'state', 'sent_lsn', 'write_lsn', 'flush_lsn',
                      'replay_lsn', 'write_lag', 'flush_lag', 'replay_lag', 'sync_state')
ORDER BY ordinal_position;
Output
 column_name 
-------------
 client_addr
 state
 sent_lsn
 write_lsn
 flush_lsn
 replay_lsn
 write_lag
 flush_lag
 replay_lag
 sync_state
(10 rows)
Column Meaning
sent_lsn WAL sent to the standby
write_lsn, flush_lsn WAL written and flushed on the standby
replay_lsn WAL applied and visible to queries on the standby
replay_lag Time between local flush and replay confirmation
sync_state async, potential, sync, or quorum

On a standby, pg_is_in_recovery() returns true.

Example 5: failover

When the leader fails, a follower is promoted.

flowchart LR
    A["Detect failure (timeout)"] --> B["Choose the most up-to-date follower"]
    B --> C["Promote it to leader"]
    C --> D["Repoint clients and other followers"]
    D --> E["Old leader rejoins as follower (rewind if diverged)"]
Risk Cause
Lost writes Async follower promoted while behind
Split brain Two nodes both act as leader; prevented by fencing and a consensus-based coordinator
False failover Timeout too short during a load spike

Tools: Patroni, repmgr, and managed services for PostgreSQL; Orchestrator and Group Replication for MySQL. pg_rewind resynchronises a former leader.

Example 6: multi-leader and leaderless replication

Model Writes go to Conflicts Examples
Leader-follower One leader None PostgreSQL, MySQL
Multi-leader Any leader (often one per region) Possible; resolved by last-write-wins, merge, or application logic MySQL Group Replication multi-primary, BDR, Galera
Leaderless Any replica Possible; resolved by versions (vector clocks) and read repair Cassandra, DynamoDB, Riak

Example 7: quorum reads and writes (W + R > N)

With N replicas, a write waits for W acknowledgements and a read queries R replicas. If W + R > N, every read set overlaps every write set in at least one replica, so a read sees the latest acknowledged write.

N W R W + R > N Behaviour
3 2 2 4 > 3 yes Strong; tolerates 1 node down for both reads and writes
3 1 1 2 > 3 no Fast, may read stale data
3 3 1 4 > 3 yes Fast reads; writes fail if any node is down
5 3 3 6 > 5 yes Tolerates 2 nodes down

Worked case (N = 3, W = 2, R = 2): a write is stored on nodes A and B, node C misses it. Any 2 nodes read from {A,B}, {A,C}, or {B,C}. Each pair includes A or B, so the newest version is always returned and the coordinator returns the highest version. The query checks the overlap condition for several settings:

SQL
SELECT n, w, r, (w + r > n) AS overlap_guaranteed
FROM (VALUES (3,2,2), (3,1,1), (3,3,1), (5,3,3), (5,2,2)) AS q(n, w, r);
Output
 n | w | r | overlap_guaranteed 
---+---+---+--------------------
 3 | 2 | 2 | t
 3 | 1 | 1 | f
 3 | 3 | 1 | t
 5 | 3 | 3 | t
 5 | 2 | 2 | f
(5 rows)

Example 8: physical vs logical replication, statement vs row-based

Physical (streaming) Logical
Ships WAL bytes (block changes) Decoded row changes (INSERT, UPDATE, DELETE)
Replica Identical copy, same major version Can differ in version, schema, and indexes
Granularity Whole cluster Selected tables (publication / subscription)
Replica writable No (read-only standby) Yes
Uses High availability, read replicas Upgrades across versions, selective copy, CDC (change data capture)

MySQL binlog formats:

Format Logs Trade-off
STATEMENT The SQL text Small, but non-deterministic functions (UUID(), NOW()) can diverge
ROW Each changed row Deterministic and the default; larger logs
MIXED Statement unless unsafe, then row Compromise

Example 9: replica reads and connection pooling

Read replicas offload SELECT traffic. The application or a proxy routes writes to the leader and tolerant reads to followers.

Concern Handling
Stale reads Route read-your-writes traffic to the leader
Long queries on standby conflict with WAL replay hot_standby_feedback, max_standby_streaming_delay
Too many connections Pool connections

A PostgreSQL connection is a separate process using several MB of memory, so thousands of direct connections degrade the server. PgBouncer (or a built-in pool such as RDS Proxy) multiplexes many client connections onto a small number of server connections.

Pool mode (PgBouncer) Server connection held for Restriction
Session The whole client session None
Transaction One transaction No session state (SET, advisory locks, prepared statements need care)
Statement One statement No multi-statement transactions

Example 10: CAP, PACELC, and consistency models

CAP theorem: during a network partition (P) a distributed system must choose between consistency (C: every read sees the latest write) and availability (A: every request gets a non-error answer). Partitions cannot be ruled out in practice, so the real choice is CP or AP during a partition.

Type During a partition Examples
CP Rejects or blocks requests on the minority side etcd, ZooKeeper, HBase, MongoDB (default majority writes), Spanner
AP Answers from any node, may be stale Cassandra, DynamoDB (eventual reads), Riak

PACELC extends it: if there is a Partition choose A or C; Else (normal operation) choose Latency or Consistency.

System If partition Else
Cassandra, DynamoDB (default) PA EL
Spanner, VoltDB PC EC
MongoDB PA EC

Consistency models from strongest to weakest:

Model Guarantee
Linearizable Operations appear to happen instantly in real-time order
Sequential All see operations in the same order, not necessarily real-time
Causal Cause is seen before effect
Read-your-writes / monotonic reads Per-client guarantees
Eventual Replicas converge if writes stop

The consistency in CAP (linearizability) is different from the C in ACID (constraints hold).

Interview points

  • Async replication can lose committed data on failover; sync replication costs latency and availability.
  • Replication lag causes read-your-writes and monotonic-read anomalies.
  • W + R > N gives overlapping quorums.
  • Physical replication copies WAL; logical replication copies row changes and supports version upgrades.
  • CAP applies only during partitions; PACELC covers the latency trade-off otherwise.
  • Replicas scale reads, not writes; sharding scales writes.

Summary

  • Leader-follower replication streams the WAL or binlog to followers; async is fast but can lose data, sync is safe but slower.
  • Lag produces stale reads; route read-your-writes traffic to the leader.
  • Failover needs failure detection, promotion, and fencing to avoid split brain.
  • Leaderless systems use quorums: W + R > N ensures a read overlaps the latest write.
  • CAP forces CP or AP during a partition; PACELC adds the latency vs consistency choice otherwise.