interviewpath
  • 0day streak
  • 10total XP
  • Level 1
0/6

Unit 5 · Distributed & cloud · Lesson 7 of 14

Retries, deadlines, overload and graceful degradation

Many prolonged outages come less from the first failure than from the reaction to it: retries multiply load, queues grow without bound and healthy services are dragged down. Timeouts, deadlines, backoff with jitter, retry budgets, load shedding, backpressure, circuit breakers and graceful degradation keep a partial failure partial.
About 4 h 30 minFocus mode

Step 1: Learn the ideas

  • Timeouts from latency percentiles
  • Deadlines and deadline propagation
  • Retry amplification across layers
  • Exponential backoff, caps and jitter
  • Retry budgets and token buckets
  • Overload, goodput collapse and queueing
  • Admission control and load shedding by priority
  • Backpressure and bounded queues
  • Circuit breakers
  • Graceful degradation and fallback risks
  • Cascading and metastable failures

Why it matters

A dependency slows down, callers time out and retry, the extra traffic slows the dependency further, queues grow, and soon services that never had a bug are failing too. That feedback loop, more than the original fault, is behind many long outages. Retries and overload come up in interviews because the naive answers (retry three times, add a bigger queue) make things worse, and because every design discussion eventually reaches "what happens when this dependency is slow?"

Core ideas

Timeouts and deadlines. Every remote call needs a timeout chosen from the dependency's latency distribution (for example somewhat above its p99.9), not a round number. Better still, the edge gives each request a deadline and passes the remaining budget downstream, so no service starts work its caller has already abandoned; servers check the deadline before expensive steps and drop requests that are already late.

Retries amplify. If each of three layers makes up to three attempts, one user request can become 27 calls at the bottom layer, exactly when it is struggling. Rules of thumb:

  • Retry only idempotent or deduplicated operations, and only errors likely to be transient.
  • Retry at one layer (usually the one with the most context), not at every layer.
  • Use capped exponential backoff with jitter, so clients that failed together do not retry together.
  • Bound retries with a budget, for example allowing retries only up to a small fraction of recent successful requests, implemented as a token bucket. While the dependency is healthy, retries flow freely; while it is failing, they stop adding load.
sleep = random_between(0, min(cap, base * 2 ** attempt))      # "full jitter"
retry only if error.retryable and budget.try_take() and deadline_remaining > sleep

Overload and goodput. When offered load exceeds capacity, queues grow, latency rises past client timeouts, and the server spends its capacity on requests whose callers have already left. Throughput can stay high while goodput (useful completed work) collapses. The cure is to refuse work early and cheaply:

  • Admission control and load shedding: reject excess requests at the front door with a clear, retry-friendly error, preferably by priority (drop prefetch and batch traffic before user-facing requests) and per tenant.
  • Bounded queues and backpressure: a full queue should push back on producers (block, reject or slow them) instead of growing. Under backlog, serving newest work first or discarding requests already past their deadline keeps the system useful.

Circuit breakers. A client-side breaker tracks recent failures to a dependency; past a threshold it opens and fails fast, then admits a few trial requests after a cool-down (half-open) to test recovery. It protects the dependency and frees the caller's threads, but each client sees only part of the picture, so breakers can flap.

Graceful degradation. Decide in advance what the product does without each dependency: serve cached or stale data, hide a recommendation panel, accept writes into a queue for later. Fallbacks that run only during incidents are rarely tested and may overload something else; prefer degraded modes that are exercised regularly.

Cascading and metastable failures. Overload spreads through shared dependencies and retries. In a metastable failure the trigger (a short spike, a cache flush) disappears, yet the system stays down because the recovery load (retries, cold caches) keeps it overloaded. Recovery then requires shedding load or blocking retries, not only fixing the trigger.

Common misconceptions

  • "Retries improve reliability." They hide rare transient errors; under sustained failure they multiply load. Budgets and single-layer retries keep the benefit without the amplification.
  • "Exponential backoff alone prevents retry storms." Without jitter, clients that failed at the same moment stay synchronized.
  • "A bigger queue absorbs overload." It converts overload into latency, and requests then time out after consuming resources; bound queues and shed load.
  • "Generous timeouts avoid errors." Long timeouts tie up threads and connections during an incident; base them on measured latency and the caller's deadline.
  • "A circuit breaker fixes overload." It limits the damage one client does; the server still needs its own admission control.

How to approach it

Read the Builders' Library articles on timeouts and on load shedding, then SRE book Ch. 21 and 22. Build intuition with a small experiment: a server with fixed capacity and a load generator whose clients retry; plot goodput as offered load passes capacity, with and without shedding, jitter and a retry budget. Graduates should know timeouts, backoff with jitter and idempotent retries. Mid-level candidates should design deadlines, budgets, shedding and degraded modes for a given call graph. Senior candidates should reason about amplification, metastability and per-tenant fairness, and explain how they would test overload behavior before production.

Suggested order

  1. 1Read the Builders' Library article "Timeouts, retries, and backoff with jitter" and the AWS retry-with-backoff pattern page.
  2. 2Read SRE book Ch. 21 (Handling Overload) for client-side throttling, criticality and limits on retries.
  3. 3Read SRE book Ch. 22 (Addressing Cascading Failures), focusing on queue management, load shedding, retries and deadline propagation.
  4. 4Read "Using load shedding to avoid overload" and Brooker's comparison of fixed retries, token-bucket budgets and circuit breakers.
  5. 5Compute the retry amplification of a four-layer call chain with three attempts per layer, then redesign it with one retrying layer and a 10 percent retry budget.
  6. 6Run the goodput experiment from the notes and record at which offered load goodput collapses without shedding.

Step 2: Check off what you can do

Tap each one you can genuinely do or explain. Each earns 10 XP.

Step 3: Go deeper

  • Site Reliability Engineering (Google SRE book)Start here

    Google (free online edition)

    Section: Ch. 22: Addressing Cascading Failures (with Ch. 21: Handling Overload)

    How overload spreads and the standard defenses: queue limits, load shedding, retries, deadlines and degradation.

    Open(opens in a new tab)Link responded, 5 Oct 2026
  • Timeouts, retries, and backoff with jitterStart here

    Amazon Builders' Library

    Choosing timeouts, retry amplification, and backoff with jitter.

    Open(opens in a new tab)Link responded, 5 Oct 2026
  • Retry with backoff pattern (AWS Prescriptive Guidance)

    Amazon Web Services

    Concise pattern description, including when retries are unsafe.

    Open(opens in a new tab)Link responded, 5 Oct 2026
  • Using load shedding to avoid overload

    Amazon Builders' Library

    Why goodput collapses under overload and how to shed load cheaply and by priority.

    Open(opens in a new tab)Link responded, 5 Oct 2026
  • Fixing retries with token buckets and circuit breakers

    Marc Brooker's blog

    Quantitative comparison of fixed retries, retry budgets and circuit breakers.

    Open(opens in a new tab)Link responded, 5 Oct 2026

Step 4: Practice

Build a small simulation or real server (any language) with fixed concurrency, a bounded queue and a load generator whose clients time out and retry. Measure goodput and p99 latency as offered load goes from 50 to 200 percent of capacity under four configurations: naive retries, backoff with jitter, a retry budget, and load shedding with deadline checks. Then take a call graph you know, for example a system you have built, and annotate each edge with its timeout, retry policy, idempotency and degraded behavior.

No external problems are linked; follow the guidance above.

Record attempts on each problem’s page (+15 XP, +10 more when solved on your own).

Step 5: Test yourself

Answer each one out loud or on paper before you finish the lesson.

  1. Question 1Why does a server that accepts every request perform worse under overload than one that rejects some?
  2. Question 2Where should retries happen in a five-service call chain, and why only there?
  3. Question 3What does jitter fix that exponential backoff alone does not?
  4. Question 4How does deadline propagation save work?
  5. Question 5What makes a fallback path dangerous?
  6. Question 6How would you recover from a metastable failure whose original trigger is gone?

You’re done when you can

  • Explain retry amplification with a computed example and two mitigations in under three minutes.
  • Write backoff-with-jitter and retry-budget logic from memory.
  • Annotate an unseen call graph with timeouts, deadlines, retry policy and degraded modes, and justify each choice.
  • Explain why goodput collapses under overload and how load shedding restores it.

Finish the lesson

How confident do you feel?

Lesson complete!

+50 XP

Reviews will come up on the Practice tab so it sticks.

Unlocks next: SLOs, incidents, capacity and tail latency, System design method

Your notes and study time

Log study time