system_design / scaling building blocks / 02_replication_and_consistency.md

Replication, sharding and consistency models

6 interview angles 5 min read source

Replication, sharding and consistency models

The scaling vocabulary. Most system design answers need these words used precisely, and imprecision here is very visible.

Replication

Copies of the same data on multiple nodes, for read scaling and fault tolerance.

Model Writes Reads Trade-off
Single-leader one node any replica simple; the leader is a write bottleneck and a failure point
Multi-leader several nodes any write availability across regions; conflicts
Leaderless (Dynamo-style) any node, quorum quorum high availability; application handles conflicts

Single-leader is the default and what Postgres and MySQL do out of the box. Multi-leader appears in multi-region deployments and brings write conflicts that need resolution — last-write-wins loses data silently, so CRDTs or application-level merge are the honest answers.

Synchronous or asynchronous

The choice that decides your failure behaviour:

Synchronous Asynchronous
Write latency leader + slowest replica leader only
Data loss on leader failure none the un-replicated tail
Availability a stuck replica blocks writes unaffected

Semi-synchronous is the common compromise: wait for one replica, let the rest catch up asynchronously. Bounded data loss, bounded latency.

Replication lag — the bug that reaches users

Asynchronous replicas are behind. That produces a specific, very common bug: a user updates their profile, the write goes to the leader, the subsequent read goes to a replica that hasn’t caught up, and the UI shows the old value.

Fixes, in order of preference:

  • Read-your-writes: route a user’s reads to the leader for a few seconds after they write. Cheap and effective.
  • Monotonic reads: pin a user to one replica so they never see time move backwards.
  • Wait for the replica to reach the write’s LSN before reading.

Naming read-your-writes unprompted is a good signal — it’s the failure people actually hit.

Sharding

Splitting data across nodes so each holds a subset. Replication copies; sharding divides.

Strategy Good Bad
Range efficient range scans hotspots — sequential keys hit one shard
Hash even distribution no range scans
Consistent hash minimal reshuffling when nodes change slightly more complex
Directory flexible, supports rebalancing the lookup service is a dependency

The shard key is the decision that’s hardest to reverse. Choose it so the common query includes it — otherwise every read becomes a scatter-gather across all shards, which is slower than not sharding.

The classic failure: shard users by user_id, then need “all orders in the last hour across all users”. That query touches every shard.

What sharding costs:

  • Cross-shard joins are gone or expensive.
  • Cross-shard transactions need two-phase commit or a saga.
  • Rebalancing moves data while serving traffic.
  • Hotspots — one celebrity user can overwhelm a shard regardless of how even the hash is.

Shard last. Read replicas, caching, a bigger box, and archiving cold data all come first. Modern hardware and Postgres go a very long way, and saying so is better than reflexively sharding a hypothetical system.

CAP, and what it actually says

Under a network partition, choose consistency or availability.

The precision that matters: CAP is about behaviour during a partition, not a general “pick two”. With no partition you get both. And “consistency” in CAP means linearizability, which is stricter than the C in ACID.

PACELC is the more useful framing: during a Partition, choose Availability or Consistency; Else (normally), choose Latency or Consistency. That second half describes the trade-off you make every day, whereas partitions are rare.

The consistency spectrum

Ordered strongest to weakest:

Model Guarantee
Linearizable every read sees the most recent write; behaves like one copy
Sequential all nodes see operations in the same order
Causal causally related operations are ordered; concurrent ones may differ
Read-your-writes you see your own writes
Monotonic reads you never see time go backwards
Eventual given no new writes, replicas converge

Eventual consistency is a much weaker promise than people assume — it says nothing about when, and permits reading arbitrarily stale data meanwhile.

Causal consistency is the sweet spot for many systems: it prevents the confusing anomalies (seeing a reply before the message it replies to) without linearizability’s coordination cost.

Quorums

W + R > N   guarantees a read overlaps a write

With N=3: W=2, R=2 is the balanced choice. W=3, R=1 optimises reads at the cost of write availability. W=1, R=1 is fast and gives no consistency guarantee.

The caveat worth knowing: quorum overlap alone isn’t linearizability. Concurrent writes, failed writes that partially applied, and read-repair timing all leave edge cases. Dynamo-style systems are eventually consistent even with strict quorums.

Interview angle

  • “Replication or sharding?” — different problems. Replication copies data for read scaling and fault tolerance; sharding divides it for write and storage scaling. Most systems need replication long before sharding.
  • “A user updates their profile and immediately sees stale data. Why?” — replication lag: the write went to the leader, the read hit a lagging replica. Fix with read-your-writes consistency, routing that user’s reads to the leader briefly after a write.
  • “How do you choose a shard key?” — so the common query contains it. If typical reads don’t include the shard key, every query becomes a scatter-gather across all shards and you’ve made things slower. It’s the hardest decision to reverse.
  • “Explain CAP.” — under a network partition you must choose availability or consistency. It’s not a general “pick two” — with no partition you get both. PACELC is more useful: during a partition choose A or C, else choose latency or consistency.
  • “What does eventual consistency actually promise?” — that replicas converge given no further writes. It says nothing about when, and permits arbitrarily stale reads meanwhile. Causal consistency is usually the better target: it rules out the confusing anomalies without full coordination cost.
  • “When would you shard?” — after read replicas, caching, vertical scaling and archiving are exhausted. Sharding costs you cross-shard joins, distributed transactions, rebalancing complexity and hotspot risk. Modern single-node Postgres handles more than people expect.