Skip to content

AI Gateway: Routing, Cost Controls, and Observability

CoreConceptJuly 28, 20268 min read

A working AI feature can become hard to operate the moment three services call three model providers with three separate keys. Nobody can answer which team spent the money, which prompt version caused a regression, or whether a fallback quietly changed the answer users saw.

An AI gateway is the boundary between application code and model providers. This guide is for engineers who already understand basic LLM API calls and want one practical outcome: route a support-triage request through a gateway that enforces policy, records evidence, handles failure, and gives teams a measurable upgrade path. For the broader production map, start with 9 AI Concepts for Production Systems and connect it to LLMOps Stack.

AI gateway map: app calls cross one controlled boundary before model providers
AI gateway map: app calls cross one controlled boundary before model providers

The Gateway Owns the Model Boundary

Treat the gateway as a control boundary, not a magic model improver. Product services still own the user experience, prompts still need evaluation, and model providers still generate tokens. The gateway owns the crossing point: identity, provider credentials, routing policy, request logging, budget checks, and safe fallback behavior.

The running example is support-triage. The app sends { tenantId, ticketId, severityHint, promptVersion } to the gateway. Success means the gateway returns a triage label plus a trace id. The intentional failure is a per-tenant budget cap: the gateway must reject or downgrade the request before it leaks provider keys or spends unplanned money.

Use an AI gateway when model access has become shared infrastructure, not a single app experiment.
PatternUse WhenWatch
Direct SDK callOne prototype, one owner, one providerKeys and logs sprawl as teams copy it
Thin gatewaySeveral apps need one auth and logging boundaryIt must not hide prompt quality problems
Policy gatewayBudgets, routing, fallbacks, and approvals matterRules need tests and visible decisions
AI gateway responsibilities compared with direct SDK calls
AI gateway responsibilities compared with direct SDK calls

Quick reference

  • Keep provider API keys out of product services; issue app-to-gateway credentials instead.
  • Route by task class, latency budget, tenant policy, data sensitivity, and measured quality.
  • Log prompt version, model, route decision, token estimate, latency, terminal status, and trace id.
  • Do not expect a gateway to fix weak prompts, stale retrieval, or missing evals.
  • Make fallback explicit: cheaper model, cached answer, human review, or typed failure.

Remember this

An AI gateway is the shared control boundary for model calls: it centralizes keys, routing, budgets, traces, and fallback decisions without replacing prompt or eval quality.

One Request Through the Gateway

The gateway path should be boring enough to debug. support-triage authenticates to the gateway, sends a typed task request, and receives either a model result or a typed refusal. Inside the gateway, policy runs before the provider call: tenant allowed, route allowed, estimated cost inside budget, prompt version known, and sensitive fields redacted or denied.

Only after those checks does the gateway choose a provider and model. The response comes back with a normalized shape so product code does not depend on every provider's error vocabulary. That normalization is useful, but it has a cost: if the gateway hides too much detail, teams cannot diagnose provider-specific latency, safety refusals, context-limit errors, or rate-limit behavior.

Support triage request flow: app, gateway policy, route, provider, normalized result
Support triage request flow: app, gateway policy, route, provider, normalized result

Quick reference

  • Validate shape and tenant before sending text to any provider.
  • Estimate cost with model, input tokens, max output tokens, and tenant budget state.
  • Normalize terminal outcomes, but preserve raw provider diagnostics in secure traces.
  • Return traceId on success and failure so support and engineering can inspect the same run.
  • Keep retry ownership clear: the gateway retries provider transport errors, not unsafe business actions.
Direct model call spread through an app
1// support-triage/api.ts2// Works at first, then every service owns keys, retries, routing, and logs.3const response = await provider.chat.completions.create({4  model: "fast-model",5  messages: [{ role: "user", content: ticketText }],6});7 8return { label: response.choices[0]?.message?.content };
Gateway call with typed policy outcome
1type GatewayResult =2  | { ok: true; traceId: string; label: string; model: string; costUsd: number }3  | { ok: false; traceId: string; code: "budget_exceeded" | "policy_denied" | "provider_unavailable" };4 5async function triage(ticket: { tenantId: string; ticketId: string; text: string }) {6  const res = await fetch("https://ai-gateway.internal/v1/tasks/support-triage", {7    method: "POST",8    headers: { authorization: `Bearer ${process.env.AI_GATEWAY_TOKEN}` },9    body: JSON.stringify({ ...ticket, promptVersion: "triage-v7" }),10  });11 12  return (await res.json()) as GatewayResult;13}

Remember this

A gateway request is useful when every terminal path is typed: success, budget stop, policy denial, provider failure, and fallback all return evidence the app can handle.

Policy and Budgets Run Before Tokens Burn

Budget control is not only a finance feature. It is a reliability feature because runaway loops, retries, and oversized context windows can turn a small incident into noisy provider traffic. Put the cap in the gateway so every service uses the same accounting boundary before the model call happens.

Policy should be boring and testable: who is calling, what task is requested, which data class is present, which route is allowed, how much budget remains, and whether the request needs approval. The gateway can downgrade from a premium model to a cheaper one, reject with budget_exceeded, or queue for human review. What it should not do is silently switch models in a way that changes user-visible quality without a trace.

Quick reference

  • Fail before the provider call when budget, task, tenant, or data policy does not allow the request.
  • Record why a route was chosen: default route, cost cap, data policy, latency target, or fallback.
  • Separate hard denies from graceful downgrades so product behavior stays intentional.
  • Measure budget at the same boundary for batch jobs, chat calls, agents, and background retries.
  • Alert on spend velocity, not just monthly totals; loops fail faster than invoices arrive.
Policy sketch
1function chooseRoute(req: GatewayRequest, tenant: TenantPolicy): GatewayDecision {2  if (!tenant.enabledTasks.includes(req.task)) return { allow: false, code: "policy_denied" };3  if (req.estimatedCostUsd > tenant.remainingBudgetUsd) return { allow: false, code: "budget_exceeded" };4  if (req.dataClass === "restricted" && !tenant.allowRestrictedModels) {5    return { allow: true, model: "local-redacted-model", reason: "data_policy" };6  }7  return { allow: true, model: tenant.defaultModel, reason: "default_route" };8}
Minimum trace fields
1{2  "traceId": "gw_01J...",3  "task": "support-triage",4  "tenantId": "acme",5  "promptVersion": "triage-v7",6  "decision": "budget_exceeded",7  "estimatedCostUsd": 0.08,8  "remainingBudgetUsd": 0.02,9  "providerCallMade": false10}

Remember this

The cheapest model call is the one the gateway blocks before tokens burn, with a trace showing the exact policy or budget rule that made the decision.

Observability Feeds the Eval Loop

Gateway logs are operational evidence, not quality by themselves. Latency, tokens, cost, route, and provider status explain how the request ran. Evals explain whether the answer was good enough. The two become powerful together when every eval failure links back to the prompt version, retrieved context ids, route decision, and model output that produced it.

For support-triage, keep a small golden set of tickets with expected labels and escalation rules. Before changing routes or models, replay the set through the gateway and compare quality, latency, and cost per ticket. A cheaper model is only a win if it preserves the pass threshold for the ticket mix you actually serve.

Quick reference

  • Trace the decision path: caller, prompt version, retrieved ids, route rule, model, latency, tokens, and terminal state.
  • Redact or hash sensitive fields before logs leave the gateway trust boundary.
  • Attach eval results to gateway releases so route changes are reviewed like code changes.
  • Compare models on the same task set; do not borrow leaderboard claims as production proof.
  • Define an upgrade threshold: quality gain, latency cost, spend impact, and rollback rule.

Remember this

Gateway observability explains what ran; evals decide whether it was good enough, so model routing changes need both traces and representative task cases.

Recover a Provider and Budget Failure

Trigger. A release accidentally increases maxOutputTokens for support-triage, and a provider also starts returning intermittent 429s. Symptom. Latency rises, monthly spend velocity spikes, and some tickets receive generic fallback labels. Root mechanism. Direct callers would each retry differently, but the gateway sees all traffic at the model boundary: estimated cost, rate-limit responses, route decisions, and fallback frequency.

Recovery: freeze the expensive prompt version, lower the route to a cheaper model for low-severity tickets, preserve high-severity tickets for the stronger route, and return provider_unavailable when no safe fallback exists. Prevention: add a spend-velocity alert, a per-task max-token policy, and a regression case that fails when the gateway silently changes labels without marking the route decision.

Failure detail: token change and provider limits recovered at the gateway boundary
Failure detail: token change and provider limits recovered at the gateway boundary

Quick reference

  • Budget failures should stop before provider calls; rate-limit failures happen after a route attempt.
  • Fallback is not always safe: legal, medical, billing, and security tasks may need escalation instead of downgrade.
  • Use idempotency keys for queued retries so a background worker does not duplicate a costly operation.
  • Keep provider raw errors in restricted traces while returning stable gateway error codes to apps.
  • Run post-incident eval replay against the exact prompt version and route policy that failed.

Remember this

A gateway makes model incidents diagnosable because cost spikes, provider limits, fallback decisions, and prompt versions meet at one observable boundary.

Key takeaway

Build an AI gateway when model access becomes shared infrastructure. It gives teams one place to protect provider keys, route by task, enforce budget before tokens burn, normalize failures, and connect traces to evals. Keep its promise precise: it controls the boundary around model calls; it does not make weak prompts, stale retrieval, or missing review magically safe.

Practice (30 min): create a tiny gateway wrapper around one existing LLM call. Start with a /v1/tasks/support-triage endpoint that accepts tenantId, ticketId, text, and promptVersion, then returns either { ok: true, traceId, label } or { ok: false, traceId, code }. Expected success: one normal ticket returns a label and trace id. Intentional failure: set the tenant budget below the estimated request cost and verify budget_exceeded with providerCallMade: false. Recovery: raise the budget or select a cheaper route, then re-run the same ticket. Pass when success, budget stop, and provider failure are all visible as distinct terminal states.

Share:

Related Articles

A bigger foundation model is often the easiest way to get strong general behavior. A small language model can be cheaper

Read

Transformers are often described as if they are a mysterious reasoning machine. At the mechanical level, they are a repe

Read

LLMs are fluent text generators; production systems need contracts. The gap shows up when a classifier returns urgent-is

Read

Explore this topic

Keep learning

Follow a structured path or browse all courses to go deeper.