Filter concepts by levelShowing all levels.

System Design · Replication

Replication

One primary, many replicas, and the freshness trade-off every replica read makes

  • Primary/replicaone writer, many copies
  • Sync vs asyncwait for ack vs confirm now
  • Read replicasscale reads, not writes
  • Replication laga growing, draining backlog

1.Primary/replica architecture and sync vs async replication

A primary/replica setup has one instance (the primary) that accepts writes, and one or more replicas that receive a continuous copy of those writes. Synchronous replication waits for a replica to confirm before the primary reports success — safer, slower. Asynchronous replication reports success immediately and streams the change to replicas afterward — faster, with a real chance of losing the most recent writes if the primary fails first.

Key features

  • Primary (leader): the only instance that accepts writes in a single-primary setup
  • Replica (follower): receives a stream of the primary's changes and applies them, usually serving reads
  • Synchronous replication: the primary waits for a replica to acknowledge before confirming the write — no data loss on primary failure, but higher write latency
  • Asynchronous replication: the primary confirms the write immediately, replicating in the background — lower latency, but the most recent writes can be lost if the primary fails before replicating
  • Semi-synchronous is a common middle ground: wait for at least one replica to acknowledge, replicate to the rest asynchronously

Synchronous vs asynchronous replication

Synchronous vs asynchronous replication
PropertySynchronousAsynchronous
Write latencyHigher — waits for replica ackLower — confirms immediately
Data loss on primary failureNone (replica has every acked write)Possible — unreplicated writes are lost
Availability if a replica is slow/downWrite can stall or failUnaffected — replica catches up later
Typical useFinancial/critical data, small clustersRead replicas at scale, cross-region replicas
Primary/replica: sync vs. async confirmation
writereplicateack receivedimmediately

Client

writes

Primary

accepts the write

Confirm (sync)

after replica ack

Confirm (async)

before replica has it

Replica

receives the stream

  • Client — writes
    • leads to Primary (write)
  • Primary — accepts the write
    • leads to Replica (replicate)
    • on error, leads to Confirm (async) (immediately)
  • Confirm (sync) — after replica ack
  • Confirm (async) — before replica has it
  • Replica — receives the stream
    • leads to Confirm (sync) (ack received)

Command

text
write → primary
primary → [sync] wait for replica ack → confirm to client
primary → [async] confirm to client → stream to replica

Primary accepts writes, replicas receive a stream of them. Synchronous replication waits for a replica ack before confirming (safer, slower); asynchronous confirms immediately (faster, can lose the newest writes on failover).

2.Read replicas and the consistency implications

Read replicas let a system scale reads horizontally by routing SELECT-style queries to replicas instead of the primary, freeing the primary to handle writes. The trade-off is consistency: a replica is only ever as current as its last applied change, so a read routed to a replica can return data that is milliseconds — or, under load, much longer — out of date compared to the primary.

Key features

  • Read replicas offload read traffic from the primary, letting reads scale independently of write capacity
  • A read routed to a replica can return stale data relative to the primary — how stale depends on replication lag
  • Read-your-own-writes is the most common consistency problem: a user who just wrote data may read it back from a lagging replica and not see their own change
  • A common fix is routing a user's own reads to the primary for a short window after they write, then falling back to replicas
  • Read replicas do not help write scalability — every write still goes through the single primary

What routing a read to a replica does and does not guarantee

What routing a read to a replica does and does not guarantee
GuaranteePrimaryRead replica
Sees every write immediatelyYesNo — bounded by replication lag
Scales independently of write loadNoYes — add more replicas
Safe for "read my own recent write"YesNot guaranteed without extra handling
Safe for analytics/reporting readsYes, but competes with write loadYes — isolates that load from the primary
Read-your-own-writes, broken by replica lag
Client
Primary
Replica
  1. 1update bio
  2. 2OK
  3. 3GET profile
  4. 4old bioreplica has not applied the update yet
  1. Client → Primary: update bio
  2. Primary → Client: OK
  3. Client → Replica: GET profile
  4. Replica → Client: old bio (replica has not applied the update yet)

Command

text
writes  → primary
reads   → primary          (need latest data)
        → replica (any)    (staleness acceptable)

Read replicas scale reads, not writes, and every replica read is a trade of freshness for capacity — the read-your-own-writes case is the one that most often needs a deliberate exception.

3.Why a just-written record may not appear on a lagging replica

Replication lag is the delay between a write landing on the primary and that same write being applied on a replica. It is caused by network transfer time, the replica applying changes in order, and the replica simply falling behind under heavy write load — it is not a bug, it is an inherent property of asynchronous replication that a design has to account for.

Key features

  • Replication lag is measured as either time (seconds behind primary) or position (bytes/log-sequence-number behind)
  • Lag grows when write volume on the primary exceeds what a replica can apply, or when network latency between them increases
  • A replica applies changes in the order it received them — it cannot skip ahead, so one slow operation can back up everything behind it
  • Cross-region replicas typically have higher, more variable lag than same-region ones, purely from network distance
  • Lag should be actively monitored — a replica silently falling further and further behind is a real production risk, not just a theoretical concern
Replication lag: normal load vs. a write burst

Normal load

  • Primary: 100 writes/sec
  • Replica applies 100 writes/sec
  • Lag stays near 0

Write burst (2 min)

  • Primary: 500 writes/sec
  • Replica can only apply ~150/sec (disk I/O bound)
  • Lag grows to tens of seconds behind
  • Normal load
    • Primary: 100 writes/sec
    • Replica applies 100 writes/sec
    • Lag stays near 0
  • Write burst (2 min)
    • Primary: 500 writes/sec
    • Replica can only apply ~150/sec (disk I/O bound)
    • Lag grows to tens of seconds behind

Command

sql
-- PostgreSQL: check replication lag from the primary
SELECT client_addr, state,
       pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn)
         AS lag_bytes
FROM pg_stat_replication;

Replication lag is a growing-and-draining backlog, not a fixed constant — it worsens under write bursts and replica resource pressure, and needs monitoring, not an assumption that it stays small.

Remember

  • Synchronous replication: no data loss on failover, higher write latency. Asynchronous: opposite trade.
  • Read replicas scale read capacity, never write capacity — every write still goes through the primary.
  • Read-your-own-writes is the most common consistency bug from naive replica read routing.
  • Replication lag is not constant — it grows under write bursts and needs active monitoring.

Pro tip

  • Route a user's own post-write reads to the primary for a short window rather than accepting the read-your-writes gap everywhere.
  • Alert on replication lag directly — a slow, silent backlog is a worse failure mode than an obvious outage.

Next up

  • Sharding and partitioning
  • Consistency models
  • Distributed locks

Sources

  • PostgreSQL documentation — postgresql.org/docs
  • Checked 2026-08-21

Spotted a mistake on this page? Tell us.