A) CAP, PACELC, and consistency models
Say
“I pick consistency per endpoint and per failure mode — not one global setting.”
CAP (only forces a choice during partitions)
- P (partition): timeouts, packet loss, region split, long GC pauses that look like a split.
- Under P, you can’t guarantee both C (linearizable reads) and A (always respond successfully).
- Real design: choose which endpoints become “strict” (C) vs “serve something” (A) when P happens.
PACELC (adds the normal-day trade)
- If P → choose A or C.
- Else → choose Latency or Consistency (e.g., cross-region quorum adds RTT).
Consistency models you can name in interviews
- Linearizable (strong): reads see the latest committed write globally.
- Sequential: everyone agrees on one order, but reads may not be “latest”.
- Causal: preserves “happens-before”; independent writes may be seen in different orders.
- Eventual / bounded staleness: replicas converge; may be stale for N seconds.
- Session guarantees: read-your-writes, monotonic reads/writes (amazing UX win).
CAP/PACELC — template (what to say + how to decide)
TemplateChecklist: • Identify your “must be correct” invariants (money, permissions, uniqueness). • Identify endpoints that can be stale (feeds, counters, recommendations). • Decide behavior during partitions: “fail closed” (C) vs “serve stale” (A). • Decide behavior when healthy: local low-latency (EL) vs quorum strong reads (EC). Interview line: “I’m PA/EL for feed reads and PC/EC for correctness paths like privacy + billing.”
Facebook-like Home Feed — CAP/PACELC choices
ExampleReads (feed timeline): • Prefer Availability + low latency → serve from nearest region (PA/EL). • Allow bounded staleness: ~1–10s. Writes (privacy settings / blocks): • Prefer Consistency → quorum write + read-your-writes (PC/EC). • During partitions: fail closed (don’t accidentally expose private content). Counters (likes/views): • Eventual with merge/CRDT; accuracy within seconds is OK.
B) Consensus & coordination (Raft/Paxos, ZooKeeper/etcd)
Say
“Consensus is for the control plane — keep it small, critical, and boring.”
What consensus gives you
- Single chosen leader (at a time) + quorum decisions.
- Replicated log: committed entries survive node failures.
- Safety: committed log entries aren’t “uncommitted” later (with correct Raft/Paxos).
Where to use (and where NOT to)
- Use: leader election, distributed locks (with fencing), config/feature flags, membership metadata.
- Don’t use: storing high-QPS business data (it will bottleneck and hurt reliability).
Consensus — template (how to explain it simply)
Template• Pick Raft-backed systems (etcd/Consul/ZK) for coordination: leaders, locks, config. • Keep payloads tiny and traffic low (control plane). • Put business data in scalable stores/streams (data plane). • Treat coordination like a dependency with strict SLOs and tight access controls.
Facebook-like Home Feed — what uses consensus
ExampleControl plane: • One “feed ranking config” source (feature flags, model version) stored in etcd. • Leader-elected “scheduler” per region triggers backfills and refresh jobs. Data plane: • Posts/reactions/events flow through Kafka/Kinesis. • Feed materialization data lives in partitioned storage (KV / wide-column / document), not etcd.
C) Leader election & fencing tokens (split-brain protection)
Say
“Leader election without fencing is incomplete — old leaders must be rejected.”
The real problem: split brain
- GC pause or flaky network can make an old leader “think” it’s still leader.
- Meanwhile a new leader is elected. Now two writers exist → corruption risk.
Fencing tokens (the fix)
- Coordinator issues a monotonic token on leadership acquisition.
- Every side-effect must carry the token; downstream stores max token and rejects lower.
Fencing token — template pseudo-code
Templatetoken = coordinator.acquire_leadership() # monotonic, e.g. 1051
while coordinator.lease_valid(token):
write_to_downstream(token, payload)
# Downstream:
# if token < max_seen_token_for_shard: reject as staleLeader election + fencing — template
Template• Use ephemeral nodes or leases for leader election. • ALWAYS attach fencing tokens to side-effects: - DB writes (store max token) - queue publishes (consumers validate token) - object store updates (conditional writes) • Prefer “reject stale writer” over “best effort”.
Facebook-like Home Feed — preventing split-brain fanout
ExampleScenario: • Region scheduler A (token=1051) publishes “rebuild feed” tasks. • A pauses (GC). Coordinator elects scheduler B (token=1052). • A resumes and tries publishing again. Protection: • Consumers store max_seen_token per partition/user. • Tasks from A (1051) are dropped; only B (1052) is accepted. Result: no duplicate or corrupt fanout.
D) Clocks & ordering (NTP, Lamport, vector clocks, HLC)
Say
“Ordering by wall-clock is a trap — order per key or via consensus.”
Clock types (what to use them for)
- Wall clock (NTP): can jump backward/forward → fine for UI timestamps, risky for correctness.
- Monotonic clock: timeouts, deadlines, backoff (per-node only).
- Lamport clock: “happens-before” ordering without detecting concurrency.
- Vector clock: detects concurrent updates (metadata grows with participants).
- HLC: hybrid logical clock → near-time + monotonic, common in multi-region DBs.
Practical ordering rules
- Total order needs consensus/log (Raft) or global sequencer.
- Per-entity order is easy: partition by entity key (order within partition).
- Don’t use timestamps for “latest wins” unless you control versioning (server-issued).
Clocks & ordering — template
Template• For correctness: avoid wall-time ordering; use consensus or server-issued versions. • For streams: ordering is per partition → choose partition keys deliberately. • For causality-sensitive merges: version vectors / HLC only where needed. • For timeouts/retries: use monotonic clocks + deadlines, never wall clock.
Facebook-like Home Feed — ordering strategy
ExampleEvents: • Partition “post events” by post_id → edits/deletes are ordered for a post. • Partition “fanout tasks” by user_id → tasks for one user are ordered. Versions: • Use server-issued version numbers (or HLC) for “profile last updated” to avoid client clock skew. Timeouts: • Consumers use monotonic deadlines for processing + retries.
E) Conflict resolution & CRDTs (LWW, merges, repair)
Say
“Pick conflict strategy per field: CRDT for intent, LWW only where safe.”
Conflict strategies
- LWW (last-write-wins): simplest; risks losing intent under concurrent writes.
- CRDTs: converge via commutative/idempotent merges (great for counters/sets).
- App merges: field-wise rules (sum/max/union), with audit + repair.
Repair / anti-entropy
- Read repair: fix divergence when you read (good for hot keys).
- Background repair: periodic reconciliation for cold keys.
- Merkle trees: compare hashes to find divergent ranges efficiently.
Conflicts & CRDTs — template (how to choose)
TemplateChecklist: • Does the field represent “intent” from many writers? (likes, follows, device list) → prefer CRDT. • Is the field “single-writer” or can be safely overwritten? (theme color, language) → LWW with server-issued version. • Are merges domain-specific? (ranking signals, counters with caps) → app merge rules + audit. Always: • Document conflict rules per field. • Add repair (read repair for hot, background repair for cold).
Facebook-like Home Feed — conflict choices by feature
ExampleReactions: • Likes/emoji counts → PN-Counter CRDT (no lost increments across regions). User lists: • “Muted creators”, “hidden posts” → OR-Set CRDT (add/remove converge correctly). Profile fields: • “Bio”, “profile photo” → LWW with server-issued version to reduce skew issues. Repair: • Hot users: read-repair on access. • Cold users: nightly background repair job.
Mini stance: multi-region settings (a clean design story)
Say
“Reads stay local; strict invariants fail closed; everything else converges.”
Design goals
- Low latency for user reads.
- Correctness for privacy and identity invariants.
- Clear conflict policy per field.
- Operational clarity (observability + replay + repair).
Toolbox
- Consensus for leaders/config.
- Async replication cross-region.
- CRDTs for intent-heavy sets/counters.
- Versioned LWW for simple fields.
Mini stance — template you can reuse
Template“I split the world into: 1) Correctness-critical invariants → strong/quorum, fail closed during partitions. 2) UX-critical reads → local/available, accept bounded staleness. 3) Intent-heavy shared state → CRDTs to avoid lost updates. Then I add fencing + repair + metrics to keep it safe in production.”
Facebook-like Home Feed — multi-region settings stance
ExamplePrivacy: • Writes require quorum; during partitions, block writes rather than risk exposure. Feed: • Reads served from nearest region; staleness ~1–10s is OK. State types: • Counters/sets: CRDT. • Simple preferences: LWW w/ server-issued versions. Ops: • Repair jobs + dashboards on divergence/conflicts + replay tools for streams.
Common pitfalls & fixes (what interviewers love)
- Pitfall: “We’re strongly consistent” (everywhere). Fix: choose per endpoint; name invariants.
- Pitfall: wall-time used for correctness. Fix: server-issued versions, consensus, HLC where needed.
- Pitfall: leader election without fencing. Fix: monotonic tokens + downstream checks.
- Pitfall: “exactly-once” belief. Fix: idempotency keys + atomic commits + dedupe stores.
- Pitfall: no repair strategy. Fix: read-repair + background repair + monitoring.
Pitfalls — template (quick close)
Template“I avoid global strong claims. I define invariants, choose per-endpoint guarantees, add fencing for leaders, use idempotency end-to-end, and back it with repair + metrics.”
Facebook-like Home Feed — pitfalls avoided
Example• Don’t order global feed by timestamps across regions (clock skew). • Don’t store feed content in etcd/ZooKeeper (control plane only). • Expect duplicates; make consumers idempotent with dedupe keys. • Always provide replay + DLQ + repair tooling.
One-liners for interviews (memorable, accurate)
- “CAP is about partitions; PACELC explains latency vs consistency on normal days.”
- “Consensus is for control-plane choices; data plane stays partitioned for throughput.”
- “Leader election needs fencing tokens; downstream must reject stale leaders.”
- “Ordering is per partition unless you pay for a sequencer or consensus log.”
- “CRDTs preserve user intent for counters/sets; LWW is for safe single-writer-ish fields.”
One clean closing line (template)
Template“For a Home Feed: PA/EL for reads, strict for privacy and billing, CRDTs for reactions, and fencing + repair for safety.”
Facebook-like Home Feed — 20-second answer
Example“Reads stay local and fast; we tolerate bounded staleness. Privacy and invariants use quorum/strong consistency. Events are ordered per key via partitioning. Counters and sets use CRDTs. Leaders use fencing tokens. And we back it all with repair, replay, DLQs, and dashboards.”