Key takeaway: Model routing sends each request to the cheapest model that can handle it; fallbacks fail a request over to a backup when the primary errors, rate-limits, or times out. Both are good reliability and cost patterns — and both quietly do the same dangerous thing: they change which model answered on a per-request basis. If your retrieval and context are not deterministic and the chosen route is not logged, a fallback that silently serves a weaker model is indistinguishable from a genuine quality regression, and you will spend a debugging session chasing the wrong variable. The decision this post helps you make: adopt routing and fallbacks for the cost and uptime — but treat the router as a load-bearing component you evaluate, pin the context so the model is the only thing that changed, and log the route plus a retrieval receipt on every request so any regression is attributable.
If you run LLMs in production, routing is nearly irresistible. Most requests are easy and a small cheap model answers them perfectly; a few are hard and need your best model. Routing captures that gap — RouteLLM's authors report over 2× cost reduction without sacrificing response quality by sending easy prompts to a weak model and only escalating hard ones (RouteLLM, arXiv 2406.18665). Fallbacks are just as sensible: when the primary provider throws a 429 or a 5xx, you want the request to survive on a backup rather than fail the user. AWS shipped this as a managed primitive — Bedrock Intelligent Prompt Routing went GA in April 2025 — and every gateway (LiteLLM, OpenRouter) has it built in.
So the "so what" is a warning that rides in with the win: the moment you route or fall back, the model is no longer a constant in your system — it is a per-request variable you often cannot see. A cost win and an uptime win are real. But they buy you a new failure mode: the answer to "why did quality drop this afternoon?" is now entangled with "which model actually ran, and on what context?" — and if you did not pin the context and log the route, that question has no answer. This post is the reliability blueprint: what routing and fallback actually are, the taxonomy of what you can route on, the specific failure modes they introduce, the architecture that keeps them debuggable, and a scorecard to grade your own setup.
Previous post: LLM Observability for RAG: Trace the Regression.
What this post covers
By the end, you should be able to look at your own inference path and say, for any request, which model answered, why the router chose it, and what context it saw — so a regression is a lookup, not an investigation.
- What routing and fallback actually are — the base distinction between choosing a model up front and failing over after an error.
- The taxonomy of what you route on — rules, cost/latency budgets, and learned router models, and the tradeoff each makes.
- The failure modes routing introduces — silent fallback degradation, the router as an unevaluated model, cascading latency, and the attribution blind spot.
- The architecture that stays debuggable — route on signals, pin the context, log the decision.
- A model-routing readiness scorecard — a worksheet to grade your setup and find the open gap.
- Where Inherent fits — why deterministic retrieval and a per-request audit are what make a routed request explainable.
Routing and fallback are two different moves, not one
Start with the distinction, because teams conflate them and then debug them as if they were the same thing. Routing is a decision made before the call: pick the best model for this request. Fallback is a reaction made after a call fails: try a different model so the request survives. They optimize different things — routing optimizes cost and quality per request; fallback optimizes availability — and they fail in different ways.
Routing is a classification problem. Given a prompt (and ideally some metadata — task type, expected difficulty, token budget, latency SLO), a router decides: does this need the frontier model, or will the small one do? Bedrock's Intelligent Prompt Routing does exactly this inside a model family, "dynamically predicting the response quality of each model for a request" and routing to the cheapest one that clears the bar (AWS). Fallback is a reliability chain. In LiteLLM's router, the primary model is tried first; on a retry-able error — 429, 5xx, context-window-exceeded, content-policy, timeout — the request moves down an ordered list of backups with exponential backoff, and there are even error-specific chains: a context-window fallback to a larger-window model, a content-policy fallback to a different provider (LiteLLM routing docs, reliability docs).
The base concept to hold onto: routing is a choice about quality; fallback is a choice about survival — but from the model's seat, both mean "a different model than the one you designed around is now generating the answer." Everything downstream — your evals, your prompts, your output parsers, your cost dashboards — was tuned for a specific model. Routing and fallback both silently violate that assumption, for good reasons, on a fraction of traffic you may not be measuring.
What you route on determines what breaks
The answer first: the smarter your router, the more it becomes a model in its own right — with its own accuracy, its own drift, and its own need for evaluation. There are three broad strategies, and they trade simplicity for quality in a predictable way.
Rule-based routing is a lookup table: if the request is tagged summarize, use the small model; if code, use the big one; if the prompt exceeds N tokens, use the long-context model. It is transparent, deterministic, and trivially debuggable — you can read the rule. Its ceiling is that it only knows what you told it; a hard question wearing an easy tag gets the cheap model and a bad answer.
Budget-based routing picks on cost and latency SLOs: send traffic to the cheapest deployment that meets the latency target, load-balance across providers by rate limit and price. This is what most gateways do by default, and it is excellent for throughput and cost — but it optimizes for the infrastructure's constraints, not the answer's difficulty, so it will happily route a hard prompt to a weak model because the weak model was cheaper and up.
Learned routing trains a small classifier to predict, per prompt, whether the weak model's answer will be good enough — this is RouteLLM's approach, learning the boundary from preference data, and it is where the 2× cost savings come from (RouteLLM, LMSYS). It captures difficulty the other two miss. The catch is the one nobody budgets for: a learned router is a model, so it has an error rate, it drifts as your traffic shifts, and it needs its own eval harness. A router that misclassifies 5% of hard prompts as easy is silently shipping 5% worse answers, and it will not show up in an error log because nothing errored.
The failure modes are all variations of "you can't see which model ran"
Here is the pattern that reorganizes how you defend the inference path: almost every routing/fallback incident is the same root cause wearing a different mask — the model that generated an answer is not the model you think generated it, and you have no per-request record to correct the assumption. Four concrete masks:
Silent fallback degradation. Your primary is a frontier model; your fallback, chosen months ago for a rare outage, is a cheaper model two tiers down. The primary starts throttling under load one afternoon, so 20% of traffic quietly fails over. No errors — the fallback works. But answer quality on that slice drops, complaints tick up, and your dashboards show green because "requests succeeded." The degradation is invisible precisely because the fallback did its job.
The router as an unevaluated model. You ship a learned router and never wire it into your eval suite. It drifts as your prompt mix changes, its misclassification rate creeps up, and each misroute is a quietly worse answer with no error attached. You evaluate your LLMs religiously and never evaluate the thing deciding which LLM runs.
Cascading latency. Fallback chains add time, not just resilience. A 429 that triggers a retry with backoff, then a fallback, then its retry, turns a fast failure into a slow success — sometimes slower than just failing would have been. Under a provider-wide incident, every request walks the whole chain, and your p99 latency detonates.
The attribution blind spot. This is the one that costs you a debugging day. Quality drops. You ask the only question that matters — did the model change, or did the context change? — and you cannot answer it, because you logged neither the chosen route nor the exact context retrieved. So you cannot tell a fallback event from a bad deploy from a retrieval regression. Three different bugs, one indistinguishable symptom.
The exhibit makes the condition for attribution explicit: a regression is only explainable when the context is held fixed and the route is logged — every other combination leaves at least one variable moving in the dark.

The architecture: route on signals, pin the context, log the decision
The answer first: you keep the cost and uptime wins and kill the failure modes by making one variable move at a time and recording which one moved. Three controls, in order.
Route on explicit signals, not vibes. Feed the router structured inputs — task class, token count, a difficulty score, the latency SLO — rather than letting it guess from raw prompt text alone. Explicit signals make the decision inspectable and testable, and they let you unit-test the router the way you test any classifier. If you use a learned router, put it in your eval harness and track its misclassification rate as a first-class metric, not an afterthought.
Pin the context so the model is the only thing that changed. This is the load-bearing move and the one most teams miss. When you route or fall back, you want to be able to say "same question, same retrieved context, different model" — because that is the only way a quality difference is attributable to the model. If your retrieval is non-deterministic (a re-embed, a re-chunk, a different index snapshot between the primary and fallback call), then routing changed two variables at once and no comparison is valid. Deterministic retrieval — same query over the same corpus version returns the same chunks — is what turns a routed request into a controlled experiment instead of a confound.
The business-life version: think of routing like a hospital triage nurse assigning patients to doctors. Triage is good — it sends the sprained ankle to the junior doctor and the chest pain to the specialist, and it saves everyone's time. But if the nurse also secretly rewrote each patient's chart on the way in, you could never tell whether a bad outcome came from the doctor or the altered chart. Routing is the nurse; the retrieved context is the chart. Route the patient, never rewrite the chart — and log both.
Log the route and a retrieval receipt on every request. Every response should carry: which model actually generated it, why the router chose it (or which fallback fired and on what error), and exactly what context it saw — sources, versions, chunks. With that record, "quality dropped this afternoon" becomes a query: filter to the bad window, see that 20% fell back to the cheap model on primary 429s, done. Without it, the same question is a forensic reconstruction.

Why this ordering holds: routing on signals makes the decision testable, pinning the context makes the model the only variable, and logging the decision makes the variable visible after the fact. Drop any one and the other two lose their value — a logged route over non-deterministic context still tells you nothing, because two things moved.
A model-routing readiness scorecard
Grade your inference path against this. Each row is a control; a row you cannot clear is a named, specific gap — not a vague "we should look at our routing."
| Control |
The question |
You're ready if |
If not |
| Route visibility |
Does every response record which model actually ran? |
Model ID + route reason logged per request |
A fallback event looks identical to a normal one |
| Router evaluation |
Is the router itself in your eval harness? |
Misclassification rate tracked as a first-class metric |
A drifting router ships worse answers with zero errors |
| Fallback awareness |
Do you alert when fallback traffic share spikes? |
An alert fires when the backup serves > X% of requests |
20% of traffic silently degrades and dashboards stay green |
| Context determinism |
Same query + same corpus version → same chunks? |
Retrieval is deterministic and version-pinned |
Routing changes two variables; no comparison is valid |
| Retrieval receipt |
Can you name the exact context a routed request saw? |
Each response carries sources + versions + chunks |
You can't tell a model regression from a retrieval one |
| Latency budget |
Do fallback chains have a bounded total time? |
Chain depth + backoff capped against your p99 SLO |
A provider incident makes every request walk the whole chain |
| Replayable route |
Can you reconstruct the exact route + context for a past request? |
Pinned corpus version + logged route per request |
An incident review ends at "we can't reproduce it" |
The pattern the scorecard exposes: the top rows are observability — see which model ran and when the mix shifts — but the bottom rows are structural. You can log every route perfectly and still be unable to explain a regression if the context underneath was non-deterministic. Visibility into the route is necessary; determinism in the context is what makes the visibility mean something.
Where Inherent fits
Only now, with the reliability model built, does the product framing earn its place — and it lands on the two structural rows of the scorecard, Context determinism and Retrieval receipt, because every routing control above quietly assumes them. You cannot run a routed request as a controlled experiment if the context moves when the model moves, and you cannot review a routing incident whose retrieval you cannot reproduce.
That is precisely the layer Inherent provides: it sits above your vector storage and below your orchestration and gateway, and it makes retrieval governed instead of best-effort. The memory layer makes retrieval deterministic and version-pinned — the same query over the same corpus version returns the same chunks — so when your router or fallback swaps the model, the context is held fixed and any quality difference is attributable to the model alone, not to a silent re-chunk or re-embed. The truth layer version-stamps and hashes every source at ingestion, which is what lets a routed request pin to an exact corpus snapshot instead of "whatever the index looked like at 3pm." The audit layer issues a retrieval receipt per request — which sources, versions, and chunks produced the context — the exact artifact a routing post-mortem needs to sit beside the route log and answer "was this the model, or the context?"
To be clear about where we are: Inherent is early, and this is an architecture argument, not a routing product. Inherent does not choose your models or run your fallback chain — your gateway does that, and it should. What managed context supplies is the missing half of debuggability: the determinism and provenance that turn "a different model answered on unknown context" into "the same context, a known model, a logged reason." Routing gives you the cost and uptime; deterministic, audited retrieval is what keeps the savings from quietly costing you answer quality you can't see.
The bottom line, and where to start
Model routing and fallbacks are worth adopting — the cost savings are real and the uptime is real. But they turn the model into a per-request variable, and a variable you cannot see is a regression you cannot debug. The fix is not to avoid routing; it is to make one thing move at a time and record it: route on explicit signals, pin the context so the model is the only change, and log the route plus a retrieval receipt so every answer is attributable.
Small task for today: take one routed or failed-over request from your logs and try to answer three questions about it. Which model actually generated the answer? Why did the router pick it, or which fallback fired and on what error? And what exact context did it see — could you re-run the identical retrieval today? If any answer is "we don't log that," you just found the gap that will cost you your next debugging session — start there. Then close the determinism-and-provenance half the routing controls depend on: start with the Inherent Public API — get started in the docs. Building your own router and hitting the "was it the model or the context?" wall? DM Flow on X with where it breaks — that's the gap we're building against.
Next read: RAG Evaluation: How to Prove a Retrieval Change Actually Improved Answers.