CMD Guide
HomeSystem DesignRedundancy

Redundancy — Active-Passive Failover, RPO/RTO, Semi-Sync Replication & Correlated Failure (Deep Dive)

The "What is Redundancy" page already derives the availability-multiplication math (0.01 × 0.01 = 0.0001) and traces a ~20-second active-passive failover timeline; the "Redundancy and Replication" page already walks synchronous, asynchronous, semi-synchronous and leaderless mechanics with a worked replication-lag example. This page does not repeat either derivation. It adds the layer interviewers actually probe on top of them: why the multiplication assumption breaks under correlated failure, and the two numbers — RPO and RTO — that turn "we have a standby" into a quantified, defensible recovery guarantee.

1. Split-brain under partition: the old active isn't dead, only unreachable

Active-passive failover has one structural trap: a network partition looks, from the monitor's side, identical to a dead primary — but the primary itself is still up, still holding client connections, still willing to accept writes. If the passive gets promoted the instant it stops hearing heartbeats, you now have two nodes that both believe they own the write path. This is exactly the failure mode traced in depth on the Heartbeat deep dive (symmetric partitions, phi-accrual detection, the blast radius of a false positive) and the Leader/Follower deep dive (externally-orchestrated failover with no term/epoch, fencing tokens, STONITH) — read those for the full mechanism. The short version this page needs: fencing (a monotonically increasing token that a downstream write path rejects if it's lower than the highest it has seen) is what makes a promotion safe even if the old active wakes back up, and it is a precondition for everything below — none of the RPO/RTO numbers in this page mean anything if a resurrected old active can still silently accept writes after "failover" completes.

2. Availability multiplication needs independence — correlated failure breaks it

The parallel-availability rule — unavailability multiplies across redundant components — is only valid if the two components fail for unrelated reasons. Two nodes in the same rack are not independent: they share a power feed, a top-of-rack switch, and often a software rollout or a config push. If either of those goes, both nodes go together, and the independence assumption the multiplication relied on is gone.

Worked contrast. Take two nodes each independently unavailable 1% of the year (p = 0.01). The naive parallel calculation says the pair is down only when both fail independently at once: 0.01 × 0.01 = 0.0001 (99.99% available, ~53 min/year downtime) — the number already derived on the "What is Redundancy" page. Now add one shared failure mode: the rack's power distribution unit fails 0.3% of the year, taking out both nodes simultaneously regardless of anything else. The real unavailability is no longer the product of the two independent terms — it is (at minimum) the sum of the independent-overlap term and the shared-cause term: 0.0001 + 0.003 ≈ 0.0031, or roughly 99.69% available — ~31× worse than the naive figure, and the correlated term is the one doing almost all of the damage. Redundancy multiplies away independent failure; it does nothing to a cause that takes out every replica in the group at once. This is the same mechanism traced in full, with the RF=3 durability arithmetic, on the DFS durability deep dive (same-rack power/switch failure, why rack-awareness bounds but doesn't eliminate the risk, why an entire remote rack going down can silently drop a block to its last copy).

Design implication: a passive standby (or a semi-sync acking replica) that lives in the same rack, same power domain, or same availability zone as the active is not buying you the independence the math assumes. Spread the standby across a genuinely separate failure domain — different rack at minimum, different AZ for anything that must survive a zone-level event — or the "two nines of protection" you think you bought is actually however unreliable the shared power/network path is, which is usually worse.

3. What actually makes sync replication block

Mechanism, in one sentence: under synchronous replication the primary withholds the client's acknowledgment until at least one replica has durably persisted the write, so "the client was told success" and "the write is unrecoverable" become the same event — at the cost of every write now depending on that replica's liveness, not just the primary's. Async replication decouples the two: the primary acks off its own local durability and ships the write afterward, so client-perceived latency stops depending on replica health, but any write acked-and-not-yet-shipped is gone if the primary dies before it ships. This mechanism, the replication-lag arithmetic, and the leaderless/quorum variant are traced with a full worked LSN-gap example on the "Redundancy and Replication" page — this page only needs the one-line mechanism above as the hook for RPO below.

4. Semi-synchronous / quorum replication: the real-world default

Pure synchronous replication (wait for every replica) and pure asynchronous (wait for none) are both extremes nobody runs at scale for a primary write path: the first couples write availability to the slowest or least healthy follower, the second accepts an unbounded loss window. Semi-synchronous / quorum replication is the standard middle ground: the primary waits for an acknowledgment from one replica (or a quorum of k out of n), not all of them, before acking the client — bounding the loss window without coupling write availability to every follower's health.

Concretely, this is what production systems actually ship:

The mechanism in all three: the primary/leader's ack is gated on a count, not a set membership guarantee — "one of my followers, whichever answers first" (MySQL semi-sync default) is weaker than "a specific named quorum that must include the one that will be promoted" (Postgres ANY k, or Kafka's ISR tracking). That distinction is exactly the pitfall in section 6.

5. RPO and RTO, computed — two clocks, not one number

RPO (Recovery Point Objective) is a data-loss measurement: how far back in time you might lose data, fixed at the instant of failure and looking backward. It is set entirely by the replication mode: async replication's RPO equals however much was acked-but-unreplicated at the moment the primary died (the replication lag at that instant); sync or quorum-commit replication's RPO is effectively 0 for any write the client was actually told succeeded, because that ack didn't happen until the surviving replica already had it.

RTO (Recovery Time Objective) is a service-restoration measurement: how long until the system accepts traffic again, starting from the same failure instant and looking forward. It decomposes into three phases that stack: detection (how long until the failure is confirmed, not just suspected — the phi-accrual / health-check-threshold tuning from the Heartbeat deep dive lives here), failover/promotion (electing or designating the new primary, replaying any queued-but-unapplied writes, opening it for traffic), and DNS/connection re-establishment (clients and load balancers noticing the new endpoint — bounded by DNS TTL, connection-pool retry/backoff, or VIP re-binding time).

Traced example

tEventWhich clock it sets
t = −45msUnder async replication, the primary has acked three writes to its clients that are still only durable locally; the replica's applied position is 45ms of writes behind.Fixes RPO — this is the loss window, decided the instant the crash happens, not something that grows afterward.
t = 0Primary crashes. The three acked-but-unreplicated writes are gone the moment this happens — RPO ≈ 45ms, already final.Crash instant: RPO is now fixed; RTO's clock starts.
t = 0 to 10sHealth checker polls every 5s, requires 2 consecutive failures before declaring the primary dead (standard "interval 5s, unhealthy-threshold 2" config).Detection phase of RTO: 10s.
t = 10s to 17sOrchestrator confirms the primary is actually down (not just slow), promotes the standby, and the standby replays whatever was queued in its apply buffer, then binds the virtual IP.Promotion phase of RTO: 7s.
t = 17s to 20sDNS/service-discovery propagation and client-side connection-pool reconnect complete; new connections land on the promoted node.Reconnect phase of RTO: 3s.
t = 20sTraffic is flowing again.RTO ≈ 20s, total.

The point the two clocks make together: RPO would have been 0, not 45ms, if those three writes had gone through semi-sync (waited for the replica that ends up promoted) instead of async — a replication-mode choice, made long before the crash. RTO would still have been roughly the same 20 seconds regardless of which replication mode was in play, because RTO is a function of detector tuning and orchestration speed, not of how durable the data was. Tightening one does not tighten the other; they are separate dials answering separate questions ("how much data can we lose" vs. "how long can we be down"), and a design review that only asks for "an SLA number" without splitting the two is asking an underspecified question.

Timeline diagram showing RPO measured backward from a crash instant as a 45ms unreplicated-write window, and RTO measured forward as three stacked phases (detect ~10s, promote+replay ~7s, DNS/reconnect ~3s) totaling ~20s
Timeline diagram showing RPO measured backward from a crash instant as a 45ms unreplicated-write window, and RTO measured forward as three stacked phases (detect ~10s, promote+replay ~7s, DNS/reconnect ~3s) totaling ~20s

Pitfalls

Judgment layer: choosing by RPO need

Takeaways

Related pages

🤖 Don't fully get this? Learn it with Claude

Stuck on Redundancy — Active-Passive Failover, RPO/RTO, Semi-Sync Replication & Correlated Failure (Deep Dive)? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.

🎨 Explain it visually

Build the mental picture, not memorization.

I just read a lesson on **Redundancy — Active-Passive Failover, RPO/RTO, Semi-Sync Replication & Correlated Failure (Deep Dive)** (System Design) and want to truly understand it. Explain Redundancy — Active-Passive Failover, RPO/RTO, Semi-Sync Replication & Correlated Failure (Deep Dive) from first principles using ONE vivid real-world analogy and a visual mental model — draw it as ASCII art or a clear step-by-step diagram — with a concrete example using real numbers. Then ask me one question to check I got the mental picture, and wait for my reply. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🤔 Walk me through it (interactive)

Socratic — adapts to where you're stuck.

Teach me **Redundancy — Active-Passive Failover, RPO/RTO, Semi-Sync Replication & Correlated Failure (Deep Dive)** interactively. Ask me ONE guiding question at a time, wait for my answer, and adapt to my confusion — build the idea with me step by step instead of explaining it all at once. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧪 Quiz me & fix my gaps

Active recall exposes what you missed.

Quiz me on **Redundancy — Active-Passive Failover, RPO/RTO, Semi-Sync Replication & Correlated Failure (Deep Dive)** with 5 questions, easy to tricky, ONE at a time. Tell me if each answer is right; at the end, explain clearly what I got wrong and why. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧠 Make it stick

Intuition + hook + flashcards for long-term memory.

Help me remember **Redundancy — Active-Passive Failover, RPO/RTO, Semi-Sync Replication & Correlated Failure (Deep Dive)** for the long term: give the one-sentence intuition, a memorable hook/mnemonic, a tiny worked example, and 3 active-recall flashcards (Q -> A). If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.

📝 My notes