Thuta Learning
BasicWeb Developmentintermediate

Timeouts and Retries

What you'll walk away with

  • Explain the core ideas behind Timeouts and Retries
  • Read the diagram and trace how a request, response, or event flows through the system
  • Explain how this applies to a real API integration you might build

Build the mental model

You already know a request eventually gets a response with a status code. What API Tutorial did not cover is what happens when it does not respond at all.

A hung connection, an overloaded server, or a dropped network packet can leave your code waiting indefinitely unless you set a client-side timeout: a hard limit after which you give up and treat the request as failed, even though the server might still be working on it.

Once a request fails, the next decision is whether to retry it, and blind retrying is a real mistake. A 4xx client error, like a malformed request body or an invalid resource ID, will fail again identically no matter how many times you resend it, because the problem is in what you sent, not in the network.

  • Temporary server failures (5xx status codes)
  • Network-level failures, like a dropped connection
  • 429 rate-limit responses, especially when the provider's docs say retrying is expected

When you do retry, spacing the attempts matters. Exponential backoff doubles the wait between each attempt, so you are not hammering a struggling server every few milliseconds.

Jitter adds a small random offset to that delay, so that many clients retrying the same failure do not all retry at the exact same instant and cause a new wave of overload. Together, backoff and jitter turn a naive retry loop into one that behaves responsibly under real failure conditions.

Timeout
A hard time limit after which a client gives up on a request and treats it as failed, because the server or network did not respond in time.
Backoff
A strategy that increases the wait between retry attempts; in exponential backoff, the delay doubles with every attempt.
text
EXPONENTIAL BACKOFF SEQUENCE
----------------------------
ATTEMPT 1 (t=0s)     FAIL
   |
   | wait 1s
   v
ATTEMPT 2 (t=1s)     FAIL
   |
   | wait 2s
   v
ATTEMPT 3 (t=3s)     FAIL
   |
   | wait 4s
   v
ATTEMPT 4 (t=7s)     SUCCESS

Delay doubles each time: 1s -> 2s -> 4s (exponential backoff)

Connect it to a real scenario

The function below simulates a client retrying a request against a fixed, pre-scripted sequence of outcomes, `["fail", "fail", "fail", "success"]`, rather than making any real network call. That keeps the example fully deterministic.

For each attempt after the first, the delay doubles: 1000ms, then 2000ms, then 4000ms, following the classic `baseDelay * 2^(attempt - 2)` formula. The loop stops as soon as it records a `"success"` outcome.

In production code you would add jitter on top of this delay and would actually `await` a timer instead of just recording the number, but the retry-and-backoff logic itself is identical to what ships in real SDKs.

Read the output as a small case study: three failures in a row would sink a naive retry-every-100ms loop into overloading a struggling server, but this schedule spreads the same four attempts across roughly seven seconds of wall-clock time, giving the server real room to recover.

Try the working example

javascript
function simulateRetries(outcomes, baseDelayMs = 1000) {
  const log = [];
  for (let attempt = 1; attempt <= outcomes.length; attempt++) {
    const outcome = outcomes[attempt - 1];
    const delay = attempt === 1 ? 0 : baseDelayMs * Math.pow(2, attempt - 2);
    log.push({ attempt, waitedMs: delay, outcome });
    if (outcome === "success") break;
  }
  return log;
}

const outcomes = ["fail", "fail", "fail", "success"];
console.log(simulateRetries(outcomes));
You should see
attempt 1: outcome=fail, waited=0ms
attempt 2: outcome=fail, waited=1000ms
attempt 3: outcome=fail, waited=2000ms
attempt 4: outcome=success, waited=4000ms

5-minute try-it

Copy `simulateRetries` and change the outcome sequence to `["fail", "fail", "success"]`. Predict the two backoff delays before running it, then run it and check your prediction.

One important caution

Retrying a 4xx client error -- resending the same malformed request just fails the same way again

Skipping jitter, so many retrying clients synchronize and hit the server in a thundering herd

Retry-After header - MDNAPI Integration & Webhooks

Easy traps

  • Retrying a 4xx client error -- resending the same malformed request just fails the same way again
  • Skipping jitter, so many retrying clients synchronize and hit the server in a thundering herd
  • If you haven't taken the API Tutorial yet, it's worth finishing that first -- this course doesn't re-teach REST/HTTP/auth basics, it builds on top of them with webhooks, testing, reliability, and integration architecture.

Exercise

Copy `simulateRetries` and change the outcome sequence to `["fail", "fail", "success"]`. Predict the two backoff delays before running it, then run it and check your prediction.

You'll know it worked when: attempt 1: outcome=fail, waited=0ms attempt 2: outcome=fail, waited=1000ms attempt 3: outcome=fail, waited=2000ms attempt 4: outcome=success, waited=4000ms