A cascade that fires on the wrong error buys a second rejection, one invoice later, and blurs the answer to the only question that mattered: which provider objected, and to what. So the chain reads the failure class before it decides where — or whether — to go next.
Selection is an ordering, not a preference. A model served by your own pool is used first, because a machine you are already paying for by the hour adds nothing per token. Below that sit the provider accounts you configured, cheapest tier that fits the request. Below those sits whatever alternate route you nominated — and nothing else.
A model with no destination at all is rejected at selection, before a single upstream call is made, and the rejection names the other entry point — the one that provisions hardware on demand — instead of guessing a provider. That is a smaller detail than it looks. The alternative is a platform that accepts the request, tries something plausible, and bills you for discovering that it was never going to work.
Failures are not interchangeable. A provider that is rate-limiting you is telling you something about itself — its quota, its capacity, this minute. A provider that rejects your request body is telling you something about the request, and every other provider on the market will tell you the same thing in the same second.
Cascading the first class of failure produces an answer. Cascading the second produces an identical rejection from a different vendor, arriving later, wrapped in a message that no longer says clearly who objected. Two of those calls are billed; one of them was never capable of succeeding.
The order below is the entire mechanism. It runs once per request — it is a decision, not a loop. Three of its six outcomes are a deliberate stop.
Every alternate in this chain is one you put there. There is no default aggregator quietly absorbing your overflow, because a platform that picks your destination has also picked your price, your data path and your jurisdiction. If you have configured nothing, a provider outage fails your request — and tells you which provider, which class of failure, and that exactly one attempt was made.
Turning fallback on is one piece of configuration, and it is reversible. What it is not is the default. That asymmetry is the whole design: the failure mode of an unconfigured chain is a visible error, not an unexplained line on an invoice from a supplier you never signed up with.
A bounded chain has a ceiling: the selected provider, and at most one alternate. That ceiling is what makes the cost of a request predictable enough to price. It also keeps the failure legible — when both attempts fail, the error names both, in order, with the class each returned.
An unbounded chain has neither property. Retry five times across three vendors and the availability graph improves, because eventually something answers. What the graph does not show is that the tail latency is now the sum of five timeouts, that requests which were never going to succeed were billed four extra times, and that the error finally surfaced is a summary of five different objections rather than the one that mattered. Availability measured that way is a number optimised against the person paying for it.
The chain here is deliberately worse on that graph and better on the invoice. The stops are not gaps in the design; they are the design.
| Situation | What the chain does | What you get back |
|---|---|---|
| Provider rate-limits you | One call to the alternate you configured. | The answer, and the name of the route that served it. |
| Provider has an outage | The same single alternate, then it stops. | The answer, or a failure naming both attempts and both classes. |
| Credential was rotated | Re-reads the credential and rebuilds the connection in place. | The answer. Nothing restarted, nobody paged. |
| Request is malformed | Nothing. The chain stops at the first rejection. | The upstream's own error, immediately, with the provider named — not a second charge and a vaguer message. |
| No alternate configured | The request fails. | A failure, rather than a surprise route on someone else's invoice. |
| Model nobody serves | Rejected at selection, before any call. | Rejected at selection, pointing at the entry point that provisions hardware on demand. |
Each page is one mechanism: what it decides, what it refuses, and why the obvious simpler version costs money. See all six →