Introduction
In our last lesson, we examined the complex and often probabilistic nature of failure detection, culminating in the adaptive approach of the accrual detector. We noted that a detector's output—declaring a node unhealthy—is just the beginning of a story. The system's reaction to that information is what truly determines its resilience. An overly aggressive or naive reaction can turn a small, localized issue into a catastrophic, system-wide outage.
This brings us to the focus of today's lesson: cascading failures. These are among the most insidious and dangerous failure modes in distributed systems, characterized by a chain reaction where one failure triggers another, leading to a domino effect that can bring an entire service down. Your ability to analyze and anticipate these patterns is a hallmark of a principal-level engineer.
We will dissect the mechanisms behind these failures, identifying the positive feedback loops that fuel them. Our primary guide will be Google's SRE book, which provides a battle-tested framework for understanding these phenomena. We'll also analyze a real-world outage at AWS to see these principles in action and introduce causal loop diagrams as a tool for visualizing these complex interactions.
The Anatomy of a Cascade: Vicious Cycles
At its heart, a cascading failure is a positive feedback loop. A small, localized fault causes a change in system behavior (e.g., rerouting traffic) which, instead of healing the system, places additional stress on other components. This stress causes them to fail, amplifying the problem and creating a vicious cycle that is difficult to escape.
Let's begin with the formal definition from the Google SRE book, which provides a clear and concise starting point.
Cascading Failures: Reducing System Outage - Google SRE
This chapter from Google's SRE book defines cascading failures and introduces the core concept of positive feedback.
Please read the introductory section, starting from the definition up to the first diagram. The example of replica overload is the simplest form of this phenomenon.
The key phrase here is "a failure that grows over time as a result of positive feedback." While the SRE book uses a simple replica overload example, these feedback loops can be much more complex. To build a more general mental model, let's turn to a presentation by Laura Nolan, a former SRE at Google and Slack.
Managing the Risk of Cascading Failure - InfoQ
This presentation transcript clearly frames cascading failures as vicious cycles and explains how our own failover mechanisms create the potential for them.
Please read two short sections: What are Cascading Failures? Note the emphasis on the system being unable to self-recover. Design to Failover. This makes a crucial point: the very tools we use for high availability, like load balancing and retries, are what create the potential for cascades.
This is a profound insight. The mechanisms we build to handle failure—redistributing load from an unhealthy backend to healthy ones—are the same mechanisms that can overload those healthy backends and propagate the failure. Reliability engineering isn't about eliminating this risk, but managing it.
Case Study: The 2015 AWS DynamoDB Outage
To make this concrete, let's analyze a well-documented cascading failure. In 2015, a portion of AWS's DynamoDB service experienced a major outage. The post-mortem reveals a classic feedback loop involving increased load, tight deadlines, and retries.
Managing the Risk of Cascading Failure - InfoQ
This section of the presentation details the sequence of events during the 2015 DynamoDB outage.
Please read the section titled DynamoDB Outage. As you read, try to identify the elements of the feedback loop: What was the initial trigger? How did the system react? How did that reaction make the problem worse? Why was simply adding more capacity not an effective solution initially?
The DynamoDB outage is a perfect illustration of a system on a "cliff edge." The system operated correctly under normal conditions, but a transient network failure was enough to push it into a vicious cycle:
- A network glitch caused some storage servers to lose contact with the metadata service.
- These servers retried, creating a wave of load on the metadata service.
- This load spike increased latency, causing more requests to miss their deadlines.
- More timeouts led to more retries, further increasing the load. This is the positive feedback loop.
- The metadata service became so overloaded that new instances couldn't synchronize and come online, making it impossible to scale out of the problem without first stopping the incoming traffic.
This kind of dynamic can be visualized using a causal loop diagram. These diagrams, from the field of system dynamics, help map out the feedback loops in a complex system. An arrow with a + means an increase in the source causes an increase in the target. A reinforcing loop, which drives cascading failures, often consists of all + connections.
/filters:no_upscale()/articles/anatomy-cascading-failure/en/resources/1Anatomy-of-cascading-failure-6-1581673058741.jpg)
Common Patterns and Triggers
The DynamoDB outage highlights a few common anti-patterns, but there are many ways a system can enter a cascading failure. The Google SRE book provides a superb taxonomy of these failure patterns. As an aspiring Principal Engineer, your goal is not just to know these patterns, but to be able to spot them in a design document or a running system.
Let's work through the most critical sections of that chapter.
Server Overload and Resource Exhaustion
The most fundamental trigger is simple overload. When a server is pushed beyond its capacity, its efficiency drops, latency increases, and it begins to shed load—often by crashing or becoming unresponsive. This is the root of most cascades.
Cascading Failures: Reducing System Outage - Google SRE
This section details the primary causes of cascading failures, originating from server overload and the exhaustion of specific resources.
Please read the entire section Causes and Design. Pay close attention to the specific effects of exhausting different resources (CPU, memory, threads, file descriptors) and how they can feed into one another. The final scenario, tracing a backend crash back to a frontend cache hit rate change, is an excellent example of the diagnostic challenges these failures present.
The key takeaway is that "overload" is not a monolithic event. It manifests as a specific resource bottleneck. A CPU bottleneck slows everything down, increasing in-flight requests and thus memory pressure. A memory bottleneck can lead to swapping and extreme latency, or an OOM kill, which takes capacity offline entirely. Understanding this causal chain is vital for both diagnosis and prevention.
Retry Amplification
If overload is the fuel, then naive retries are the spark. A client that observes a failure and immediately retries can dramatically amplify a small, transient problem into a major outage. This "retry storm" or "thundering herd" is a classic pattern.
Cascading Failures: Reducing System Outage - Google SRE
This resource explains how naive retry logic can destabilize a system and offers best practices for safer retry behavior.
First, read the section on Retries in the SRE book. The Go example clearly shows how a simple retry loop can multiply the load on a struggling backend. Then, for a slightly different perspective on best practices, read section eight, Dangerous Client Retry Behavior, from the InfoQ presentation transcript (resource_id="4c171"). It emphasizes the importance of exponential backoff and jitter.
The combination of these two resources gives you the full picture. The problem is retry amplification; the solutions include:
- Bounding retries: Never retry indefinitely. For user-facing requests, more than a few seconds of retrying is pointless.
- Exponential backoff: Increase the delay between each successive retry to give the backend time to recover.
- Jitter: Add a small amount of randomness to the backoff delay. This prevents thousands of clients from retrying in perfect synchrony, which would create synchronized waves of load against the backend.
Latency, Deadlines, and Bimodal Behavior
In a complex microservices architecture, managing latency is critical. A slow downstream service can tie up resources (threads, memory) in an upstream service. Without proper deadline management, this can cause a cascade.
Cascading Failures: Reducing System Outage - Google SRE
This section covers several advanced but critical concepts related to latency management in preventing cascades.
Please read the section on Latency and Deadlines. Focus on three key concepts: Deadline Propagation: Understand why passing a single, absolute deadline down the call chain is superior to each service having its own local timeout. Cancellation Propagation: This is the logical extension: when a client gives up, that cancellation should be propagated downstream to stop useless work. Bimodal Latency: The scenario described here is crucial. A small percentage of very slow requests can consume a disproportionate amount of capacity, dramatically increasing the error rate for all other requests.
This section is particularly relevant to Google's infrastructure, which has deeply integrated support for deadline propagation. The "bimodal latency" problem is a subtle but powerful example of how a small, partial failure can have a non-linear, outsized impact on overall system availability.
From Analysis to Prevention
Understanding these patterns is the first step. The next is designing systems that are robust against them. While we will cover specific mitigation strategies in the next lesson, it's useful to see a high-level overview of the main defense mechanisms. These strategies are all designed to break the positive feedback loops we've been analyzing.

These three patterns directly counter the cascading failure mechanisms:
- Circuit Breakers: Break the retry amplification loop by stopping requests to a known-bad dependency.
- Bulkheads: Prevent the spread of resource exhaustion from one component to another.
- Graceful Degradation / Load Shedding: Directly combat server overload by reducing the work a server has to do, keeping it within its capacity limits.
Conclusion
Today we've moved from detecting individual node failures to analyzing how an entire system can collapse. We've seen that cascading failures are not random acts of nature, but predictable outcomes of positive feedback loops inherent in our designs for high availability.
Here are the key takeaways:
- Cascading failures are driven by positive feedback loops, where a system's response to a partial failure exacerbates the problem.
- The very mechanisms for failover, like load balancing and client retries, create the potential for these cascades.
- Common dangerous patterns include server overload, resource exhaustion, retry amplification, and poor handling of latency and deadlines.
- Analyzing real-world outages and using tools like causal loop diagrams can help build intuition for these complex dynamics.
We concluded with a preview of key prevention strategies. In our next lesson, we will dive deep into the design and implementation of these solutions, covering how to design effective retry strategies, circuit breakers, bulkheads, and adaptive rate limiting to build systems that are resilient by design.