A percentage is not a measurement
A gateway that routes has to answer one question about itself: compared to what? A saving only exists relative to something that did not happen. So the number depends entirely on the baseline, and the baseline is almost never stated.
Compare against the most expensive frontier model on every request and you can manufacture any percentage you like — nobody was going to send their whole workload to the flagship. Compare against a blended average of what customers happen to use and you are measuring your customer mix, not your router. Compare against nothing in particular and put “up to” in front of it, which is the industry standard, and you have written a number that cannot be wrong because it does not mean anything.
There is exactly one baseline that survives scrutiny unlabelled: the model the caller asked for. They named it, so it is not hypothetical. The token counts are the real ones from the request that just completed, so the arithmetic is not a projection. And the answer can come out negative, which is the property that makes it a measurement rather than a marketing claim.
What that looks like on one request
A caller asks for Claude Opus 5 and sends a short prompt. The router scores it, decides it does not need a flagship, and serves Claude Haiku 4.5 instead. The response comes back with 400 input and 140 output tokens.
Those rates come from the same registry that bills the request, read at build time — a page arguing that savings numbers should be checkable cannot carry arithmetic that quietly goes wrong the next time a provider reprices.
It is a fraction of a cent. That is the point. Multiply it by the number of requests a production workload makes in a month and you have a real figure, arrived at by addition rather than by assertion — and every term in the sum is one you can check.
And it comes back on the response that caused it:
< HTTP/1.1 200 OK < x-lobstack-request-id: req_8f3a1c92e0b74d16 < x-lobstack-model: claude-haiku-4-5 < x-lobstack-tier: small < x-lobstack-complexity: 25 < x-lobstack-routed: true < x-lobstack-cost-usd: 0.001100 < x-lobstack-savings-usd: 0.004400 < x-lobstack-baseline-model: claude-opus-5 < x-lobstack-baseline-reason: named < x-lobstack-baseline-usd: 0.005500 < x-lobstack-priced: true < x-lobstack-metered: true
The three baseline headers travel with the figure and never without it, because a saving you cannot see the other side of is an assertion. x-lobstack-baseline-reason is the field that makes the number readable: it says named here, which is the like-for-like case argued above.
Nothing to query afterwards, nothing to correlate by request id, no dashboard. A caller can log it, alert on it, show it to a customer, or bill it through — because it arrived in the same place as the answer.
Who actually ships what
Here is the part we would leave out if we were selling rather than explaining. When we first wrote this argument, it said no vendor exposes what a request would have cost on the model it did not choose. That was wrong within days.
LiteLLM computes the counterfactual, and does it carefully. The baseline is stated — the most expensive model in the hardest tier the router configures. It is adjusted for a warm cache. The classifier’s own cost is subtracted, which most people forget. The result is signed, so it can admit routing lost money. That is a more rigorous definition of savings than most of this category’s marketing, and it is in a proxy you can self-host in production for nothing, under MIT — with an enterprise carve-out we have not established this feature falls outside.
The difference is where the number goes. LiteLLM’s savings figure reaches the operator: a daily-activity rollup, a cost dashboard, a column in the spend log. It answers “did routing save us money last month”. It is in no response header and no response body, so the caller who made the request cannot read it, and nothing downstream of the call can act on it.
OpenRouter went the other way and got further than most people realise. Opt into a header and the response tells you which routing strategy ran, gives you a one-line summary of the decision, and lists the candidate endpoints it considered with a flag on the one it picked. That is more disclosure about a routing decision than anyone else offers. The candidates carry no prices, so you can see it chose among five and not what the other four would have charged.
Portkey declines the question by design. It does not pick a model for you — you write the rules — so there is no decision to explain. Its cost accounting is careful, including overrides for rates you negotiated yourself, and it lives in the dashboard: the inference response carries exactly four headers and none of them is money.
So the claim that survives
Not “we route and they don’t” — most of them route, and one routes free. Not “nobody measures savings” — LiteLLM measures them well. What is left is narrow and, as far as we can verify, still ours:
The counterfactual belongs on the request that caused it, in the response the caller already has.
Everything else in this category treats the price of a routing decision as reporting — something you review later, in aggregate, in a product built for whoever pays the bill. Putting it in the response path makes it data instead: available to the code that made the call, at the moment it made it, without a second request or a plan upgrade.
Two qualifications on that receipt
Those headers are on a buffered response. Set stream: true and they are gone — not by choice: on a streamed response the headers are written before the provider has reported a single token, which is the same constraint that keeps cost out of a header at every gateway on these pages. The figures move to the final frame of the stream, next to the token counts, and the metering docs say which path carries what. We would rather you read that here than find it after you integrated.
On auto there is no model you asked for, so the like-for-like comparison above does not exist. We do not leave the field empty: the baseline becomes the most expensive model your plan allows — what you would have paid had you asked for the best one — and x-lobstack-baseline-reason reads plan_ceiling instead of named. It is a real subtraction between two real prices. It is also the most flattering number available to us, which is exactly why it is labelled and why the CLI prints “vs ceiling” rather than “saved”. Read the reason or do not read the figure.
The receipt is on every call, and there is a page where you can watch the router score a prompt and price the decision before you send anything.
Every claim about another vendor here was checked against their own documentation on 2026-09-10 and is linked from that vendor’s comparison page. This category moves faster than the pages written about it; if you are reading this long after that date, check them yourself. If we have something wrong, tell us and we will correct it on the page rather than quietly.


