Tutorial
Learn API resilience
Every API call can fail: the server is slow, overloaded or restarting, the connection drops, or you've sent too many requests. A resilient client handles all of it. It waits a sensible time, retries what is safe to retry, backs off when asked, never charges a customer twice, and stops calling a service that is clearly down.
These lessons explain each of those ideas from the start, then build them in plain JavaScript with no libraries. Every failure in them is real: the API at https://api.testingapis.comhas endpoints that fail on purpose, and every output shown is what the code printed when it ran against them. You'll need to know some JavaScript, including async, await and fetch. If HTTP status codes are new to you, start with the API testing tutorial. Some endpoints need a free account; set your key in TESTINGAPIS_KEY and the example project sends it with every request.
Download the example project
resilience-examples.zipOne file per lesson, 33 tests and the demo scripts. Node.js 22 or later, no dependencies. Unzip and runnpm test.8 lessons3 levelsFree
Beginner
2 lessonsWhat can go wrong when you call an API, how each failure looks from your code, and deadlines.
Intermediate
3 lessonsSending a request again: when it helps, when it's safe, how long to wait, and what to do about a 429.
- 03Retries: when to send a request againTemporary or permanent, safe or unsafe to repeat, and a retry loop tested against a failing server.
- 04Backoff and jitter: how long to wait between triesFixed, exponential and random waits, and why a thousand clients retrying together is a problem.
- 05Rate limits, 429 and Retry-AfterHow servers count requests, what the headers mean, and a client that waits as long as it's told.
Advanced
3 lessonsRetrying payments without charging twice, giving a failing service a rest, and testing all of it.
- 06Idempotency keys: retrying without duplicatesA payment that timed out but went through, and the header that makes retrying it safe.
- 07Circuit breakers: stop calling a broken serviceClosed, open and half-open, a breaker built from scratch, and what to show users meanwhile.
- 08Testing a client's resilienceFault injection, fake clocks, time limits in assertions, and a test suite for the whole client.
Words you'll meet
15 termsEach one is explained properly in its lesson. This list is for looking one up later.
| Term | Meaning | Explained in |
|---|---|---|
| Transient failure | A failure that goes away by itself, such as an overloaded server or a dropped connection | Lesson 1 |
| Permanent failure | A failure that repeats until the request changes, such as a 404 or a missing field | Lesson 1 |
| Timeout | The longest a client will wait for a response before treating the request as failed | Lesson 2 |
| Percentile (p99) | The time that 99 out of 100 requests beat; the basis for choosing a timeout | Lesson 2 |
| Retry | Sending the same request again after a failure | Lesson 3 |
| Idempotent | Safe to repeat: doing it twice has the same effect on the server as doing it once | Lesson 3 |
| Backoff | The pause before a retry, usually growing after each failure | Lesson 4 |
| Jitter | Randomness added to the pause, so many clients don't retry at the same moment | Lesson 4 |
| Thundering herd | Many clients retrying in step, hitting a recovering server in waves | Lesson 4 |
| Rate limit | A cap on how many requests a client may send in a period; going over gets a 429 | Lesson 5 |
| Retry-After | A response header saying how long to wait before trying again | Lesson 5 |
| Idempotency key | A unique value sent with a request so the server can recognize a repeat and not act twice | Lesson 6 |
| Circuit breaker | A switch that stops calls to a failing service for a while, so they fail fast | Lesson 7 |
| Fallback | What a client does instead when a call fails, such as showing cached data | Lesson 7 |
| Fault injection | Causing failures on purpose, to test how code handles them | Lesson 8 |