Fault Tolerance: Redundancy, Failover, and Error Recovery
Why this matters: availability and reliability are outcomes you want. Fault tolerance is the machinery that produces them. This is where the abstract targets from the last three lessons turn into replicas, failover policies, and money.
Key takeaway
Fault tolerance is a system's ability to continue operating even when one or more components — software or hardware — fail. Achieving 100% fault tolerance is practically impossible; systems aim to maximize persistence and minimize disruption.
Why it is mandatory at scale
Large-scale applications run hundreds of servers and databases to serve billions of users. At that size, component failure is not a possibility to plan for — it is a daily occurrence. These systems must eliminate single points of failure, both to keep data safe and to avoid redoing computationally expensive work every time a machine dies.
Fault tolerance rests on the two qualities from the previous lessons:
- Availability — the system remains accessible and receives client requests at any time.
- Reliability — the system consistently processes requests and performs the correct actions.
Two approaches to a single point of failure
| Approach | Strategy | Mechanism | When it applies |
|---|---|---|---|
| Fault removal | Detect the error and correct the state | Forward or backward error recovery | The fault is recoverable in place |
| Fault masking | Prevent the fault from affecting output at all | Redundancy | You have spare capacity to absorb the loss |
Fault masking is what most distributed systems lean on: keep enough redundant copies that a failure never becomes visible to a user. Fault removal is what you fall back on when masking isn't possible.
Forward and backward error recovery
Forward error recovery identifies the error state and corrects it, driving the system onward to a valid state — classically, exception handling (as in Ada or PL/1). You know what went wrong and how to fix it in place.
Backward error recovery restores the system to a stable state that existed before the fault. You don't need to understand the error — you only need a known-good state to return to. This is what checkpointing implements, and it's the subject of the next lesson.
| Recovery type | Requires | Cost | Example |
|---|---|---|---|
| Forward | Knowing the error and its correction | Cheap — no state to store | Catch the exception, substitute a default, continue |
| Backward | A saved prior state | Storage plus lost work since the save | Roll back the transaction; restore the checkpoint |
Failover strategies
When a component dies, how fast does its replacement take over? That is a cost decision:
| Mode | Backup state | Downtime on failure | Resource cost |
|---|---|---|---|
| Hot | Running, warm, receiving updates | Effectively zero | Highest — you pay for idle capacity |
| Warm | Running but not fully current | Seconds to minutes | Moderate |
| Cold | Not running; started on demand | Minutes to hours | Lowest |
Hot failover instantly transfers workloads to a functioning backup, giving zero downtime. Warm or cold failover loads and starts the backup only when needed — a delay, but far fewer resources consumed.
Map this straight onto your availability target: at 99.99% you have about 4 minutes of budget per month, so cold failover is arithmetically impossible and even warm is tight. Your availability number chooses your failover mode for you.
Replication
Replication-based fault tolerance duplicates services and data. If a node fails, the system transparently swaps it with a healthy replica. It is the dominant fault-masking technique in practice.
Keeping replicas updated forces the trade-off from Chapter 1:
| Update mode | Consistency | Availability | Cost |
|---|---|---|---|
| Synchronous | Strong — replicas agree before acknowledging | Reduced — a slow or dead replica blocks the write | Write latency bounded by the slowest replica |
| Asynchronous | Eventual — replicas lag; stale reads possible | Higher — writes succeed even if replicas are down | Data loss window if the primary dies before replicating |
Synchronous updates ensure strong consistency but reduce availability. Asynchronous updates improve availability but result in eventual consistency and stale reads. This trade-off is central to the CAP theorem — the same decision, arrived at from the fault-tolerance direction rather than the consistency direction.
Sizing redundancy
How many spares? Two standard postures:
| Model | Meaning | Survives | Cost overhead |
|---|---|---|---|
| N+1 | One spare beyond what load requires | Any single failure | Low — one extra unit |
| N+2 | Two spares | A failure during planned maintenance | Moderate |
| 2N | A full duplicate set | Loss of an entire set — a whole AZ or DC | 100% |
| 2N+1 | Full duplicate plus a spare | A DC loss plus a component failure | Highest |
Blast radius
The mature framing is not "will this fail?" but "when it fails, how much goes with it?"
Cell-based architecture partitions the fleet into independent cells, each a full stack serving a slice of users. A bad deploy or a poison request takes down one cell — a third of users, or a tenth — instead of everyone. Combined with staged rollouts, it converts total outages into partial ones, which is often the difference between an incident and a catastrophe.
Related tactics worth naming:
- Bulkheads — separate resource pools per dependency, so one saturated downstream can't consume every thread.
- Graceful degradation — shed features, not the whole service. Recommendations off, checkout still works.
- Static stability — the system keeps running on its last-known-good configuration when the control plane is unreachable, rather than failing because it can't ask permission.
The cost side
The primary purpose of fault tolerance is to prevent system unavailability, which is critical for safety-critical systems (air traffic control) and platforms requiring high data integrity. But these systems are expensive: they require redundant hardware and complex synchronization logic, and that complexity is itself a source of failure.
Key takeaway
Fault tolerance is bought, not wished for. Every nine costs redundant capacity, synchronization machinery, and operational complexity. The engineering skill is spending it where a failure actually hurts — and consciously leaving the rest to degrade.
Interview signal by level
| Level | What a strong answer sounds like |
|---|---|
| L4 | "We'll have replicas so if one fails another takes over." |
| L5 | Specifies the mechanism: "hot standby with health-checked automatic failover, and semi-sync replication to bound data loss." |
| Staff+ | Sizes and contains it: "three replicas at a 66% utilization ceiling so losing one doesn't cascade. Redundancy only covers independent faults, so bad code is handled by canaries and rollback instead. And I'd cell-partition to cap blast radius at a third of users." |
Next: what backward error recovery actually requires — and why saving state is harder than it sounds.