Fallbacks and graceful degradation

Learn to choose fail-open or fail-closed for each feature, and build fallback chains, circuit breakers, bulkheads and request timeout budgets in JavaScript.

  • 40 min
  • Expert

By now a single call in your system is well behaved. It has a deadline, it retries only what a second attempt can fix, and it stops dead on a 429 with zero credits left. That is necessary, and at system level it is not enough. A checkout page that calls five APIs has five dependencies that will each, at some point this year, be slow or unavailable for longer than any retry loop should wait. The question stops being "how do I make this call succeed?" and becomes "what does this feature do when the call cannot succeed?"

That question has a design answer, and it should be written down before the outage, not improvised during it. This lesson covers the four pieces of that answer: a failure posture chosen per feature, a fallback chain that walks from best answer to honest failure, a circuit breaker that decides when to stop trying, and the isolation (bulkheads and timeout budgets) that keeps one sick dependency from taking the healthy ones down with it.

Decide the posture per feature, not per API

Every dependency failure ends in one of two places. Fail open means the feature proceeds as if the check passed or the enrichment was optional. Fail closed means the feature stops, or routes the case somewhere slower and safer, until the dependency answers.

Neither is correct in general. The choice comes from comparing two costs: what a wrong "yes" costs you, and what a wrong "no" costs you. Work through it for each feature that depends on an external call:

FeatureDependencyWrong yes costsWrong no costsPosture
Weather widget on a dashboardWeather forecastNothing; there is no yesA blank cardFail open: hide or show stale
Signup email checkEmail validationA junk account you can clean laterA real customer turned awayFail open, flag for re-check
Signup VPN or datacenter signalVPN detectionSome fraud gets one step furtherFriction for honest usersFail to a softer path (extra verification)
Payout to a new payeeSanctions screeningA possible legal violationA delayed payoutFail closed: hold as pending
Card-not-present fraud scoreSeveral signals combinedA chargebackA lost saleDepends on order value; decide with the business

Two things fall out of the table. First, the same API can sit under features with different postures. An IP lookup that only personalises a landing page fails open; the same lookup feeding a fraud rule may not. Posture belongs to the feature, so it lives in the feature's code, not in a shared client wrapper. Second, "fail closed" rarely means "show an error". It usually means "put this case in a state that a later process or a human will resolve": a payout marked pending, an order held for review. Fail closed is a queue, not a wall.

Check yourself

A marketplace pays sellers weekly. The payout job calls a sanctions screen for any payee whose details changed. The screening dependency is timing out. What posture should the payout feature take?

Run every example on your own key. Free plan, no card.

Scaling up?

Volume pricing, custom SLAs, and dedicated support for high-traffic teams.

Contact sales