Failover
Failover for system design interviews: active-passive vs active-active, failure detection with health checks and heartbeats, DNS and load balancer switching, RPO and RTO, split brain and fencing, and realistic failover times.
On this page
- Picture it first: failover is a timeline
- Active-passive vs active-active
- Detecting failure without crying wolf
- Switching traffic to the new owner
- The two numbers: RPO and RTO
- Split brain: two primaries at once
- Failing back, and testing all of it
- How it shows up in design problems
- How to say it in the interview
🔁 What is failover?
Failover is moving work from a component that has failed to a healthy copy that was waiting for exactly this moment. It has three steps: notice the failure, decide who takes over, and switch traffic to them. A co-pilot is the everyday version: they've been flying alongside the whole time, so when the captain can't continue, they take the controls without anyone rebuilding the plane.
For this lesson, we'll focus on the switch itself: the two main topologies, how a system decides something is dead, how traffic finds the new owner, and the two ways it goes wrong (losing data and ending up with two primaries). Interviewers love asking "what happens when your primary database dies?" because a one-word answer ("replicas!") is easy, and a good answer has to cover timing, data and correctness at once.
Below the line (out of scope)
- Finding the boxes that need a failover plan: Single point of failure
- How much uptime a failover buys you: Availability and the nines
- Sync vs async replication in depth: Data replication
- Losing a whole region, backups and DR tiers: Disaster recovery
The 30-second answer
Failover has three phases: detect, decide, switch. I detect with health checks or heartbeats and declare a node dead only after several consecutive misses, so one slow response doesn't trigger it. A quorum or an external coordinator decides who takes over, and the old primary is fenced so it can't keep accepting writes. Traffic moves by updating DNS, a virtual IP or a load balancer pool. Then I state two numbers: RPO, the writes I can lose (zero with a synchronous standby, the replication lag with an async one), and RTO, the time users wait (detection plus promotion plus the switch). For a managed database I'd quote the vendor's figure, for example AWS says RDS Multi-AZ instance failovers typically take 60 to 120 seconds.
What you’ll learn
- Break any failover into detect, decide, switch, and say what each phase costs
- Choose between active-passive (hot, warm, cold) and active-active for stateless services and databases
- Tune detection with consecutive-failure thresholds and multiple observers so blips don't trigger failovers
- Estimate RPO and RTO for a setup, and quote a vendor's documented failover time
- Prevent split brain with a majority quorum, fencing and term numbers
01Picture it first: failover is a timeline
Most people picture failover as one event. In practice it's a short sequence, and each step costs time, so I always draw it as a timeline.
A failover, second by second
Notice three things:
- Detection is deliberately slow. You wait for several missed checks because declaring a healthy node dead is expensive. That wait is part of the outage.
- Promotion needs a decision. Something has to agree that the old primary is gone and pick one successor. Done carelessly, this is how you get two primaries.
- The switch depends on clients. Changing a DNS record takes seconds. Clients that cached the old address keep using it until their cache expires.
02Active-passive vs active-active
There are two basic shapes. Pick based on how much you'll pay to shorten recovery, and whether your data can live with more than one writer.
| Topology | What the spare is doing | Recovery | Cost | Catch |
|---|---|---|---|---|
| Active-passive, hot standby | Running and replicating continuously, ready to promote | Fastest of the passive options | Paying for a full idle copy | The standby isn't serving, so it's easy to stop testing it |
| Active-passive, warm standby | Running, smaller, or needs to catch up | Slower: scale up or replay first | Cheaper | Capacity surprises during the incident |
| Active-passive, cold standby | Nothing running; rebuilt from images and backups | Slowest | Cheapest | Recovery steps that nobody has run in months |
| Active-active | Every copy serves real traffic | Remove the dead one from rotation | Pay for headroom on every copy | Writes on more than one node need conflict handling |
For stateless services, active-active is the default and failover is almost free: the load balancer drops an instance that fails its health check and the rest absorb the load, if you left headroom. For databases, single-writer active-passive is the usual answer, because two writers on the same rows need conflict resolution. When I hear "active-active database", I ask how conflicts are resolved, and the answer had better be specific.
03Detecting failure without crying wolf
A machine can't tell "dead" from "slow" or "unreachable from where I'm standing". All it sees is silence. Every detection scheme is a bet on how long to wait.
- Heartbeats. The node sends "I'm alive" every interval; miss enough and it's presumed dead. We cover the mechanics in Heartbeats.
- Health checks. Something outside probes the node, ideally with a request that touches its real dependencies, not just "process is up".
- Consecutive-failure thresholds. One failed probe proves little. Requiring several in a row trades detection speed for fewer false alarms.
- Many observers and a quorum. One checker behind a bad switch will see everyone as dead. Several checkers in different places, with a majority rule, filter that out.
Amazon Route 53 documents all four. Its health checkers in several locations probe each endpoint every 30 seconds, or every 10 seconds for an extra charge. You set a failure threshold, the number of consecutive checks that must fail before the status flips. And it only marks an endpoint unhealthy if 18% or fewer of its checkers report it healthy, so a network problem near one checker doesn't fail you over.
Many candidates set the detection timeout as low as possible ("we fail over within a second") because faster feels better. It's frequently a mistake: a GC pause, a burst of load or a brief network blip then looks like a death, and you pay a full failover, with its data-loss risk, for something that would have fixed itself. Worse, the "dead" node often comes back, so you flap between primaries. Tune detection to be slower than your normal hiccups and faster than your RTO budget, and add a cooldown so a node can't be failed over to and away from repeatedly.
04Switching traffic to the new owner
Once there's a new primary, clients need to find it. Four common mechanisms:
| Mechanism | How it works | Watch out for |
|---|---|---|
| DNS update | The service name now resolves to the new node's address | Clients and resolvers cache answers until the TTL expires; some runtimes cache longer |
| Virtual IP move | A floating IP is reassigned to the new machine | Usually limited to one network or data centre |
| Load balancer or proxy pool | The LB stops routing to the failed member | The LB itself must be redundant, or it becomes the SPOF |
| Client-side list | The client knows all nodes and asks who leads, or retries the next one | Logic lives in every client library; see Service discovery |
The DNS row matters because many managed databases fail over that way. AWS documents that an RDS Multi-AZ failover changes the DNS record of the instance to point at the standby, and recommends configuring the JVM's DNS cache TTL to no more than 60 seconds, because some Java configurations cache a lookup until the JVM restarts. That's a failover that worked on the server and never reached the app. DNS basics are in Domain Name System.
05The two numbers: RPO and RTO
Every failover answer should end with two numbers.
- RPO (recovery point objective): how much recent data you can afford to lose. It's set by replication. A synchronous standby acknowledges each commit before the client hears "ok", so a committed write is never lost, at the cost of extra latency on every write (AWS notes that Multi-AZ can add write and commit latency for this reason). An asynchronous replica lags behind, and whatever it hadn't received when the primary died is gone or stranded.
- RTO (recovery time objective): how long users wait. It's detection plus decision plus switch, as the timeline showed.
Data replication covers the replication modes, and Databases for system design interviews shows replication lag in practice. Disaster recovery covers setting RPO and RTO targets for a whole region.
Try it yourself first
Before reading on, estimate both numbers for this setup. A primary database replicates asynchronously to one replica that usually runs about 2 seconds behind, at 500 writes a second. A health checker probes every 10 seconds and needs 3 consecutive failures. Promotion takes about 15 seconds. Clients find the primary through DNS with a 60-second TTL. What's the worst-case RPO and RTO?
Here's how I'd work it out loud. All of these are assumptions for the exercise, so measure your own.
| Piece | Rough number | Why |
|---|---|---|
| Detection | 20 to 30 s | The first failed probe can land up to 10 s after the crash, then two more probes 10 s apart |
| Promotion | about 15 s | Given (measure yours) |
| Switch | up to 60 s | A client may have cached the old address just before the change |
| RTO, worst case | about 105 s | 30 + 15 + 60 |
| RPO | about 2 s, roughly 1,000 writes | 2 s of lag x 500 writes/s, all acknowledged to users |
Notice which number drives the design. The DNS TTL is the largest piece of RTO, so lowering it, or using a proxy that clients don't cache, helps more than speeding up promotion. And the RPO says a payment system can't use async replication for its ledger, because 1,000 acknowledged payments might disappear.
Realistic failover times from vendor documentation, not guesses. AWS states that RDS Multi-AZ DB instance failovers (one synchronous standby) typically take 60 to 120 seconds, and that Multi-AZ DB cluster failovers (one writer, two readable standbys, semisynchronous replication) typically complete in under 35 seconds. Both repoint a DNS name, so add your clients' DNS caching on top. If your interviewer asks "how long?", quote a figure like this and name what it includes.
06Split brain: two primaries at once
Here's the failure that turns a short outage into a long one. A partition cuts the primary off from the cluster but not from all its clients. The cluster presumes it dead and promotes a replica, and now two nodes both accept writes.
Split brain, and how fencing stops it
The defences stack:
- Decide by majority. Use an odd number of voters (3 or 5) and require a majority to promote. A minority side of a partition can't elect anyone. This is what Consensus algorithms like Raft give you (see also leader election).
- Fence the old primary. Make it physically unable to write: cut its power or network, revoke its storage access, or let its lease expire before promoting anyone. The PostgreSQL docs call the blunt version STONITH ("Shoot The Other Node In The Head") and warn that without some such mechanism you can end up with two primaries and, eventually, data loss.
- Number the leaders. Each promotion gets a higher term or epoch, and storage or downstream services reject requests with an older one. A primary waking up from a long pause then finds its writes refused. Distributed locking uses the same idea under the name fencing tokens.
On 21 October 2018, maintenance cut connectivity between GitHub's US East Coast network hub and its primary East Coast data center for 43 seconds. Orchestrator, their MySQL failover tool built on Raft, reached quorum on the other side and promoted West Coast databases. When the link came back, applications wrote to the new West Coast primaries, but the East Coast servers held a few seconds of writes that had never replicated. With different writes on each side, GitHub couldn't safely fail back, and the result was 24 hours and 11 minutes of degraded service. The lesson I take from it: automated cross-region failover has its own failure modes; it isn't a free safety net.
07Failing back, and testing all of it
After a failover you're running on one copy with no spare (the PostgreSQL docs call it a degenerate state). Rebuild a standby straight away, rejoining the old primary as a replica only after discarding writes the new primary never saw. Whether you then fail back is a choice, but make it a planned, practised operation.
A failover that has never been exercised is a hope, not a plan. Trigger it on a schedule in a quiet window and measure the RTO you actually get. Fault tolerance covers chaos testing more broadly.
08How it shows up in design problems
Failover matters wherever state can't be rebuilt in seconds.
- Design a payment system: the ledger needs RPO zero, so a synchronous standby in another zone, fencing, and idempotent retries from clients while the switch happens.
- Design a key-value store: leader-based partitions need leader election per partition, plus a story for writes the old leader accepted but never replicated.
- Design a distributed lock: the lock service itself fails over, so the interesting question is how a client that held a lock on the old leader is stopped, which is fencing again.
At this point, you should ask your interviewer how much data loss is acceptable. "Zero" and "a few seconds" lead to different designs, and asking shows you know that.
09How to say it in the interview
When I ask "what happens when the primary dies?", I'm listening for four things: detection without false alarms, who decides and how you prevent two primaries, how clients find the new one, and your RPO and RTO.
In the interview
"Writes go to a single primary with a synchronous standby in another availability zone, so a committed write survives losing the primary: RPO is zero, at the cost of a cross-zone round trip on every commit. Health checks from several locations mark the primary dead only after three consecutive failures, so a GC pause doesn't trigger a failover. A quorum-based coordinator promotes the standby and bumps the term number, and the old primary is fenced, so even if it comes back it can't accept writes. Clients reach the database through a DNS name with a short TTL, and I'd make sure our runtime honours it. If we used a managed database like RDS Multi-AZ, AWS documents typical failovers of 60 to 120 seconds, so I'd plan for about two minutes of write unavailability and have clients retry idempotently during it. Reads can keep flowing from replicas. And I'd test the failover on a schedule, because one that's never been exercised probably won't work at 3 a.m."
On the whiteboard
- Failover = detect → decide → switch
- Active-passive (hot / warm / cold) vs active-active (stateless: default)
- Detect: health checks + N consecutive misses + many observers
- Switch: DNS (TTL!) · virtual IP · LB pool · client-side list
- RPO = data lost (sync 0, async = lag) · RTO = detect + promote + switch
- RDS Multi-AZ instance ≈ 60-120 s · Multi-AZ cluster < 35 s (AWS docs)
- Split brain → majority quorum + fencing + term numbers
- After: rebuild the standby, test failover on a schedule
Further reading (5)
- Failing over a Multi-AZ DB instance for Amazon RDS (AWS docs): Typical failover times of 60-120 seconds, DNS-based switching and the JVM DNS TTL advice.
- Failing over a Multi-AZ DB cluster for Amazon RDS (AWS docs): The faster variant: typical failovers under 35 seconds with two readable standbys.
- How Amazon Route 53 determines whether a health check is healthy (AWS docs): Check intervals, failure thresholds and the 18% rule that stops one bad vantage point from failing you over.
- PostgreSQL documentation: Failover: Primary source on promotion, the degenerate state afterwards and why you need STONITH-style fencing.
- October 21 post-incident analysis (GitHub Blog, 2018): How a 43-second partition and automated cross-region failover led to 24 hours of degradation.