Area 05 // AI System DesignLesson 82 / 14015 min read
Model routing, fallbacks and LLM gateways
Model routing sends each request to the cheapest model that can handle it, fallbacks automatically retry on another model or provider when one fails, and an LLM gateway puts both (plus keys, limits, caching and logging) in one layer between your apps and every model.
Think of it like this
Analogy
A hospital triage nurse sends sprained ankles to the nurse practitioner and chest pains to the cardiologist: the right specialist for each case, without wasting the expensive one on easy cases. That's routing. When the cardiologist is in surgery, the case goes to the on-call doctor instead of waiting: that's a fallback. The front desk that handles all of this, plus records and billing, is the gateway.
The problem it solves
Using one strong model for every request is simple but expensive: most requests are easy enough for a model 10–20× cheaper. And depending on one provider means that when it has an outage, rate-limits you or returns overload errors, your product goes down with it. Every team ends up writing routing, retry and fallback code, plus key management and logging, in each app. A single shared layer solves it once.
How it works: model routing
- Classify requests by difficulty or type: simple FAQ, extraction, long-document analysis, code, agent tasks.
- Map classes to models: cheap and fast for easy, strong (or reasoning) for hard (small vs large).
- Decide how to route:
- Rules: length, keywords, feature, customer tier.
- A classifier trained on labelled examples.
- A cheap LLM call that picks the route (query routing).
- Cascade: try the cheap model first and escalate when a check fails (low confidence, failed validation).
- Evaluate each route: does the cheap model pass the evals for its traffic? Measure cost saved vs quality lost.
- Monitor: share of traffic per route, quality per route, escalation rate.
How it works: model fallbacks
- Define a chain: primary model → backup model (maybe another provider) → last resort (a simpler response or a queue).
- Trigger on: timeouts, 5xx errors, overloads, rate limits (429), and sometimes refusals or invalid output.
- Retry wisely: retry the same model once or twice with backoff for transient errors, then fall back (retries); keep a total time budget.
- Add a circuit breaker: after repeated failures, skip the failing model for a cool-down period instead of trying it every time.
- Keep prompts and features compatible: the backup must support the tools, structured output and context length you use; test it with your evals.
- Log which model served each request for debugging and cost tracking.
How it works: LLM gateways
- An LLM gateway sits between your apps and all providers and exposes one API (often OpenAI-compatible).
- It centralises: routing rules, fallbacks and retries, provider keys (apps never hold them), per-team budgets and rate limits, caching (semantic caching), logging and tracing, and sometimes guardrails.
- Options (as of November 2026): open-source LiteLLM (a Python library with a
Router, and a proxy server), cloud AI gateways (e.g. Cloudflare AI Gateway, cloud providers' model hubs), and commercial gateways. - Apps change one URL to switch or add models; policy changes happen in one place.
- Run it reliably: it's now on the critical path, so make it highly available and fast.
- Support app to LLM gateway
- Search app to LLM gateway
- LLM gateway to Strong model: hard requests
- LLM gateway to Backup model: if A fails
- LLM gateway to Small model: easy requests
See it in code
- Install
pip install litellm- Needs
- Python 3.10+. Runs offline: LiteLLM's mock_response simulates an outage and the backup's answer. Model IDs as of November 2026.
A simple difficulty router, and a real LiteLLM Router falling back from a failing model to a backup.
import os
os.environ["LITELLM_LOCAL_MODEL_COST_MAP"] = "True" # don't download the price list at import
os.environ["LITELLM_LOG"] = "ERROR"
from litellm import Router
# 1) ROUTING: send each request to the cheapest model that can handle it.
def pick_model(question: str) -> str:
hard = len(question) > 200 or any(w in question.lower() for w in ("analyse", "compare", "code"))
return "strong" if hard else "fast"
for q in ["What are your opening hours?", "Compare these two contracts and list the risks"]:
print(f"{q[:40]!r:45} -> {pick_model(q)}")
# 2) FALLBACKS through a gateway library (LiteLLM). mock_response simulates an outage offline.
router = Router(
model_list=[
{"model_name": "strong", "litellm_params": {"model": "anthropic/claude-sonnet-5-5", "api_key": "x",
"mock_response": Exception("529 overloaded")}},
{"model_name": "strong-backup", "litellm_params": {"model": "openai/gpt-6.1-sol", "api_key": "x",
"mock_response": "Answer from the backup."}},
],
fallbacks=[{"strong": ["strong-backup"]}], # if 'strong' fails, try 'strong-backup'
num_retries=0,
)
r = router.completion(model="strong", messages=[{"role": "user", "content": "Compare these contracts"}])
print("served:", r.choices[0].message.content, "| by", r.model)'What are your opening hours?' -> fast
'Compare these two contracts and list the' -> strong
served: Answer from the backup. | by gpt-6.1-solIn production, remove mock_response, read real keys from environment variables, set num_retries and timeouts, and usually run LiteLLM as a proxy server (a gateway) configured with a YAML file so every app shares it.
A real example
Example
Surviving a provider outage, and halving the bill
A customer-service platform used one provider's strong model for everything. During a two-hour provider incident, their product returned errors to every customer. Afterwards they put a gateway in front: requests try the primary model with a 20-second budget, then a backup from another provider (prompts tested against both with their eval suite), with a circuit breaker.
They also added routing: a cheap model handles greetings, order lookups and FAQ answers (about 60% of traffic), passing evals at 97% of the strong model's score. The next provider incident caused a small latency bump and no errors, and the monthly bill fell by about half.
The easy way
Start here
Start with two things: (1) a fallback to a second model for timeouts and 5xx errors, tested with your evals; (2) one routing rule that sends your most common easy request type to a cheaper model. A library like LiteLLM makes both a few lines of config.
When you grow: the production setup
Teams run a gateway as shared infrastructure with routing policies per feature, cascades with quality checks, fallbacks across providers and regions, circuit breakers, per-team budgets and keys, caching, guardrails, full tracing of which model served each request, and continuous evals per route.
Trade-offs
What you gain
- Routing cuts cost substantially where cheap models are good enough.
- Fallbacks keep the product up during provider incidents.
- A gateway centralises keys, limits, logging and policy.
What it costs you
- Every route and fallback model needs its own evals and prompt compatibility.
- The gateway becomes critical infrastructure and adds a small hop of latency.
- Routing mistakes send hard requests to weak models.
When not to use it
- Very small apps with one model and low stakes: a direct SDK call with retries is enough.
Common mistakes
- Fallback models that were never tested with your prompts or tools.
- Retrying a dead provider over and over without a circuit breaker or time budget.
- Routing by guesswork instead of evals per route.
- Each app holding its own provider keys.
- Not logging which model actually served a request.
Interview questions
Try answering out loud first, then open the model answer.
How would you reduce LLM cost without hurting quality?
Model answer
Route requests by difficulty: a cheap model for simple, high-volume cases and a strong model for hard ones, using rules, a classifier, or a cascade with validation and escalation; verify each route with evals. Combine with prompt caching, semantic caching for repeated questions, trimmed contexts, capped outputs and batch APIs for offline work, and monitor quality per route.
Design reliability for an LLM feature that depends on a third-party API.
Model answer
Set timeouts and a total latency budget, retry transient errors with exponential backoff and jitter, fall back to a second model or provider (tested with the same evals and feature set), add a circuit breaker for failing providers, degrade gracefully (cached answers, simpler responses, queue for later) when all fail, and monitor error rates and which model served each request. Centralise this in a gateway.
What does an LLM gateway provide?
Model answer
A single endpoint for all apps that abstracts providers, with routing and load balancing, retries and fallbacks, centralised credential management, budgets and rate limits per team or tenant, caching, request logging and tracing, sometimes guardrails and PII redaction, and analytics on cost and usage. It decouples apps from providers so model changes are configuration, not code.
Quiz
Pick an answer to see whether it’s right and why.
0 of 5 answered
Key terms
- Model routing
- Sending each request to the most suitable model, typically cheap models for easy requests and strong models for hard ones.
- Model fallback
- Automatically sending a request to a backup model or provider when the first one fails, times out or is rate limited.
- LLM gateway
- A service between your app and model providers that handles routing, fallbacks, retries, keys, rate limits, caching and cost tracking in one place. LiteLLM is a common open-source example.
- Rate limit
- A cap on how many requests or tokens a client may send in a period. Providers return HTTP 429 when you exceed theirs.
- Circuit breaker
- A pattern that stops calling a failing service for a while after repeated errors, sending traffic to a fallback instead, then tests it again later.
Before and after
Progress is saved in this browser only.