TL;DR
These are some ways to optimize OpenRouter speed versus cost: :nitro for the fastest live host, sort: "throughput" with max_price to cap what that speed costs, and :batch when nobody is waiting. Or a quick Python function against the endpoints API gets you both at once, ranking hosts by speed then price and pinning the winner.
Same slug, different hosts
If I send a plain model id (z-ai/glm-5.3-flash, openai/gpt-5.2, and the rest), OpenRouter’s default ranking is closer to price / balanced than fastest.
That is visible on a model page. Different companies host the same model. Throughput and latency are not the same from one row to the next.

In my own testing on a cached-context chat workload, z-ai/glm-5.3-flash on default routing averaged ~221s per prompt across a 20-prompt run. Output quality was very good. The wait was not. There is a rumor going around that hosts of this model serve it on non-Nvidia accelerators, which would show up as throughput.
Nitro is the routing mode that sorts for speed. If I do not ask for it, I should not expect the fastest host.
The one-line fix: :nitro
Append :nitro to the model id. Same chat-completions endpoint, same headers, no extra fields.
{
"model": "z-ai/glm-5.3-flash:nitro",
"messages": [{ "role": "user", "content": "..." }]
}
Nitro does two things:
- Sorts eligible providers by throughput (tokens/sec). Same effect as
provider.sort: "throughput". - Lets priority-tier endpoints compete. They win only if they are actually fastest, unlike forcing
service_tier: "priority".
I pay the tier that served the request. If a priority endpoint wins, I pay priority rates. If it sheds to default, I pay default.
On the same GLM workload above, :nitro averaged ~152s per prompt vs 221s on default routing. A 3-prompt speed check on identical prompts saw 194s vs 282s — about 31% faster. Real speedup. Still slow (more on that below).
Docs: Nitro variant
When I want control instead of a suffix
Throughput, no priority pool. Fastest default endpoints, usually cheaper than Nitro:
{
"model": "z-ai/glm-5.3-flash",
"provider": { "sort": "throughput" }
}
Time-to-first-token. I use "sort": "latency" if I care about first byte more than tokens/sec.
Cheap but not slow. Keep price ranking, require a minimum p90 throughput:
{
"model": "z-ai/glm-5.3-flash",
"provider": {
"sort": { "by": "price" },
"preferred_min_throughput": { "p90": 40 }
}
}
I pin or skip hosts with provider.only, provider.ignore, or provider.order if one provider is consistently slow.
Speed first, then price
:nitro is max speed. This pick is the fastest host I would actually pay for. OpenRouter’s request object sorts by one key. sort: "throughput" plus max_price is the documented combo: highest tokens/sec, drop anyone above a ceiling. Price is not a second sort key on the wire. It only knocks out outliers. Provider routing says it in those words: use the provider with the highest throughput, as long as it does not cost more than $x/m tokens. The 1 and 2 below are OpenRouter’s own example ceilings, not a live rate. I put in what I will actually pay.
{
"model": "z-ai/glm-5.3-flash",
"provider": {
"sort": "throughput",
"max_price": { "prompt": 1, "completion": 2 }
}
}
One thing to know about the ceiling: max_price is per-token USD and OpenRouter’s actual bill can run well above a chars / 4 token estimate on long context. On one of my recent 20-prompt runs, billed cost came in about 66% higher than the char/4 guess. Set the ceiling with headroom or you will filter out hosts you would have been happy to pay.
When two hosts are close on speed, I want the cheaper one to win. That tie-break is not a routing field. I rank the endpoints list myself in Python: throughput_last_30m.p50 first (tokens/sec), then pricing.prompt plus pricing.completion (USD per token, as strings). Throughput on that route is only filled when the request is authenticated.
import requests
def pick_fastest_then_cheapest(model, api_key):
author, slug = model.split("/", 1)
r = requests.get(
f"https://openrouter.ai/api/v1/models/{author}/{slug}/endpoints",
headers={"Authorization": f"Bearer {api_key}"},
)
r.raise_for_status()
def rank(e):
tps = (e.get("throughput_last_30m") or {}).get("p50") or 0
price = float(e["pricing"]["prompt"]) + float(e["pricing"]["completion"])
return (-tps, price)
return min(r.json()["data"]["endpoints"], key=rank)["tag"]
Feed the returned tag back into provider.only on the next chat call and the router will pin the winner.
Don’t confuse “batch” with “fast”
:nitro is live inference. :batch (and POST /api/beta/batches) is async, cheaper work. I submit, poll, and wait. Great for overnight evals. Useless if the user is staring at a spinner.
:floor is the other shortcut: cheapest provider, not fastest.
Perceived speed still matters
Routing only picks the host. For a chat UI:
- Stream the completion so the first tokens show up immediately.
- Keep prompts tight. A huge RAG context inflates both TTFT and total time no matter which provider wins.
- Measure wall clock and tokens/sec separately. A long answer on a fast host can still feel slow.
When routing is not enough — switch the model
Routing picks a host of a model. Picking the model is a separate call. On the same 20-prompt cached-context workload I mentioned earlier:
| Model | Route | Avg / prompt |
|---|---|---|
| GLM 5.3 Flash | default | 221s |
| GLM 5.3 Flash | :nitro | ~152s |
| Gemini 3 Flash | default | 46s |
:nitro gave GLM back about a third of its speed. It did not close the gap with a different model on default routing. Same context, same prompts, same judge. The fastest answer was a different slug.
If the base model is the bottleneck, no :nitro, sort, or preferred_min_throughput can rescue it. Benchmark a second slug the same way — with quality and cost checks — and then let the router optimize whatever you ship.
A practical rule
| Goal | What to send |
|---|---|
| Fastest live chat | model: "...:nitro" |
| Fast, skip priority pricing | provider.sort: "throughput" |
| Fastest under a price ceiling | sort: "throughput" + max_price |
| Lowest cost | model: "...:floor" or provider.sort: "price" |
| Cheap with a speed floor | sort by price + preferred_min_throughput |
| Overnight / bulk | Batch API, not Nitro |
| Slow model, no routing tweak helps | Try a different slug |
Speed on OpenRouter is not a mystery. It is telling the router I care about throughput, paying for it when the fastest endpoint is a priority tier, and switching the model when even the fastest host of it is still too slow.