SOFTWARE ARCHITECTURE / SYSTEM CONCEPT BRIEF

Retry

The retry pattern re-executes an operation that failed due to a transient fault, such as a dropped connection, a timeout, a 503, or throttling.

BeginnerPhase 08 / Topic 13 of 17RequirementsTrade-offsFailure modes
01

Overview

The retry pattern re-executes an operation that failed due to a transient fault, such as a dropped connection, a timeout, a 503, or throttling. Many failures in distributed systems are momentary, so a well-behaved retry turns them into successes invisible to users.

Retries must be safe and controlled: retry only idempotent operations (or use idempotency keys), only retryable errors, with exponential backoff and jitter, a small maximum number of attempts, an overall deadline, and ideally a retry budget. Uncontrolled retries are a leading cause of cascading failures and retry storms.

Knocking again

If nobody answers the door, you wait a moment and knock again, maybe twice more with longer pauses. You do not pound on the door nonstop, and after a few tries you leave a note instead.

02

When to use it

  • Network calls that occasionally fail transiently.
  • Cloud APIs with throttling (429) responses.
  • Database failovers and connection resets.
  • Message processing with temporary downstream issues.
03

Where it shows up in interviews

Transient fault handling

Recognize it when: calls occasionally fail with timeouts or 503s.

  • Design a client SDK for an API
  • Design a payment processor integration
04

Where it is used in real software

AWS SDK retry modes

Standard and adaptive modes with exponential backoff, jitter, and client-side rate limiting.

gRPC retry policy

Service config defines retryable status codes, max attempts, and backoff.

Google SRE retry budgets

Limit retries to about 10% of requests per client to avoid overload amplification.

05

Key terms

Transient fault
Temporary failure likely to succeed if retried.
Backoff
Waiting longer between successive attempts.
Jitter
Randomness added to delays.
Retry budget
Cap on retries as a fraction of requests.
Deadline
Total time allowed including all attempts.
06

How it works, step by step

  1. 1
    Fail the attempt quickly

    Per-attempt timeout.

  2. 2
    Check retryability

    Error type and operation idempotency.

  3. 3
    Back off with jitter

    Random delay up to an exponentially growing cap.

  4. 4
    Stop at limits

    Max attempts, deadline, budget, or open circuit breaker.

  5. 5
    Surface the failure

    Return a clear error or fallback, log with context.

07

Which failures to retry

HTTP and gRPC responses

Step 1 / 6
ResponseRetry?Reason
Connection reset / timeoutYes (if idempotent)Transient network issue
429 Too Many RequestsYes, honor Retry-AfterThrottling
503 Service UnavailableYes, with backoffTemporary overload
400 / 422NoRequest is invalid
401 / 403No (refresh token first)Auth problem
409 ConflictDependsRe-read state first

NOWResponse: Connection reset / timeout | Retry?: Yes (if idempotent) | Reason: Transient network issue

Retrying non-retryable errors wastes resources and hides bugs.

08

Implementation

import java.time.Duration;import java.util.concurrent.Callable;import java.util.concurrent.ThreadLocalRandom; public final class Retry {    public static <T> T withBackoff(Callable<T> op, int maxAttempts, Duration base, Duration cap) throws Exception {        for (int attempt = 0; ; attempt++) {            try {                return op.call();            } catch (Exception e) {                if (!isRetryable(e) || attempt + 1 >= maxAttempts) throw e;                long ceiling = Math.min(cap.toMillis(), base.toMillis() * (1L << attempt));                long sleep = ThreadLocalRandom.current().nextLong(ceiling + 1); // full jitter                Thread.sleep(sleep);            }        }    }     private static boolean isRetryable(Exception e) {        return e instanceof java.net.SocketTimeoutException            || e instanceof java.net.ConnectException            || (e instanceof HttpStatusException h && (h.status() == 429 || h.status() >= 500));    }     public static final class HttpStatusException extends Exception {        private final int status;        public HttpStatusException(int status) { super("HTTP " + status); this.status = status; }        public int status() { return status; }    }}
09

Complexity and performance

Max extra loadx maxAttempts

Per layer that retries.

Worst-case latencyattempts x timeout + delays

Bound by a deadline.

10

Trade-offs

Success rate vs load

Retries improve success during blips but increase load exactly when a dependency is struggling.

Latency

Users wait longer for requests that need retries; keep attempts few and fast.

11

Variants and related techniques

Hedged requests

Send a parallel duplicate after a delay rather than waiting for failure.

Async retries

Delay queues and retry topics for background work.

12

Common mistakes

  • Retrying at every layer.

    Fix: Retry at a single layer to avoid multiplicative storms.

  • Retrying POSTs without idempotency keys.

    Fix: Duplicate orders or charges; add idempotency first.

  • Fixed delays without jitter.

    Fix: Synchronized clients hit the service in waves.

13

Interview questions

What makes a retry strategy safe?

Retrying only idempotent operations and transient errors, exponential backoff with jitter, a low attempt limit, an overall deadline, respecting Retry-After, retry budgets, and circuit breakers to stop when a dependency is down.

What is a retry storm?

When many clients or layers retry a failing service simultaneously, multiplying load and preventing recovery. It is prevented with backoff, jitter, budgets, single-layer retries, and circuit breakers.

14

Practice problems

ProblemDifficultyWhat it trains
Implement retry with jitter and a deadlineEasyBackoff.
Design retry policy across 3 service layersMediumAmplification.