# Smart Routing

> How AnyRouter picks an upstream provider for each request. Priority order, automatic failover, model aliases, and explicit override controls.


# Smart Routing

Every request to AnyRouter flows through a routing layer that picks the best upstream provider for the requested model. Routing is deterministic by default and configurable per-request.

## How a model maps to an upstream

AnyRouter maintains a list of **upstream candidates** for every model id. The list is pulled from `config/upstreams.yaml` (and per-model overrides in `config/models/**/*.yaml`) and ordered by `priority`. On each request, the router walks the list in priority order and routes to the first healthy candidate.

Example: `anthropic/claude-sonnet-4.6` has three candidates — `anthropic_direct` (priority 1), `openrouter` (priority 2), and `cf_ai_gateway` (priority 3). Under normal conditions every request goes to `anthropic_direct`. If Anthropic's API returns 5xx or times out, the router immediately falls through to `openrouter` and records the failure.

## Failover

A candidate is marked **unhealthy** for a short window when it:

- Returns a 5xx status.
- Times out (`timeout_ms` exceeded).
- Exhausts its rate-limit budget.

Unhealthy candidates are skipped until the cooldown expires. Requests that hit the fallback are flagged in your audit log with the final backend id, so you can see at a glance when fallback is being used.

## Forcing a specific upstream

Set the `X-AnyRouter-Provider` header on any request to pin it to a single candidate:

```bash
curl https://anyrouter.dev/api/v1/chat/completions \
  -H "Authorization: Bearer ar-your-key" \
  -H "X-AnyRouter-Provider: openrouter" \
  -H "Content-Type: application/json" \
  -d '{"model": "openai/gpt-4-turbo", "messages": [{"role": "user", "content": "hi"}]}'
```

Useful for:

- **Reproducibility** — pin to a specific provider so your eval results don't silently drift when the router fails over.
- **BYOK tests** — verify a specific BYOK credential is working end-to-end.
- **Outage debugging** — route around a failing provider without waiting for the health cooldown.

If the forced provider is unhealthy, the request fails immediately — there is no fallback when you override the router.

## Model aliases

Some models have multiple slugs that resolve to the same upstream, for compatibility with other gateways. For example, `anthropic/claude-sonnet-4.6` and `claude-sonnet-4.6` both route to the same backend. Canonical slugs are `provider/model`; bare slugs are resolved by lookup.

## Rate-limit headers

Every response includes rate-limit metadata for **both** the AnyRouter key and the upstream candidate that served the request:

```text
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 599
X-RateLimit-Reset: 1760000060
X-Upstream-RateLimit-Remaining: 998
```

Use these to back off gracefully — the router will start failing over if the selected candidate's upstream limit is close to exhaustion, but clients that respect the header get smoother behavior.
