Upgrading an LLM looks like the cheapest change in your codebase. You replace "gemini-2.5-flash" with "gemini-3.5-flash" and redeploy. One string, no new library, no new API.
On your invoice it is not one string. On the same traffic, that edit makes the bill 4.1 times bigger. The same kind of edit on Claude Sonnet makes it a third smaller. The version number tells you nothing about which way the price will move.
What changes when you change the model string
Every request names a model by its model ID — the string like gpt-5.6 that you pass in the model field. You pay per token: a chunk of text, roughly three-quarters of an English word. Prices are quoted per million tokens and split in two: input tokens are everything you send (instructions, chat history, documents), output tokens are what the model writes back. Output typically costs 4 to 8 times more than input.
Each model ID has its own pair of prices. When a vendor ships a new version, it sets a new pair, and nothing obliges it to go down. Sometimes the new model is cheaper to run and the vendor passes that on. Sometimes the new model is positioned a tier higher and priced like it.
Your code doesn't notice either way. The request format is identical, the response looks the same, and the price change arrives silently at the end of the month.
Six upgrades, one workload
To compare like with like, I fixed one workload: a small app that sends 20 million input tokens and gets back 4 million output tokens a month, a 5:1 ratio. Then I priced it before and after a same-vendor upgrade, using the vendors' list prices (their own published per-token prices) from our catalog snapshot of 16.10.2026.
| Upgrade | Old, in / out per 1M | New, in / out per 1M | Monthly bill | Change |
|---|---|---|---|---|
| claude-sonnet-4-5 → claude-sonnet-5.5 | $3 / $15 | $2 / $10 | $120 → $80 | −33% |
| claude-opus-4-5 → claude-opus-5.5 | $5 / $25 | $4 / $20 | $200 → $160 | −20% |
| gpt-4o → gpt-5.6 | $2.50 / $10 | $2 / $12 | $90 → $88 | −2% |
| gpt-4o-mini → gpt-5.6-mini | $0.15 / $0.60 | $0.20 / $1.20 | $5.40 → $8.80 | +63% |
| gemini-2.5-flash → gemini-3.5-flash | $0.30 / $2.50 | $1.50 / $9 | $16 → $66 | +313% |
Same direction in the name, opposite directions on the bill. Both Anthropic upgrades got cheaper. OpenAI's flagship stayed flat, while its small model doubled its output price. Google's Flash line went up the most: five times on input, 3.6 times on output. A sixth pair I checked, gemini-2.5-pro → gemini-3.1-pro, comes out +35% on the same workload.
The bottom two rows are the trap for beginners. Small, cheap models are the ones tutorials hardcode, and "cheap" in an older tutorial is a statement about an older price list.
When the answer depends on your traffic
The gpt-4o → gpt-5.6 row deserves a second look. Input got cheaper by $0.50 per million, output got pricier by $2. Which one wins depends on your mix, and the break-even is exactly 4 input tokens per output token. At 4:1 the bill doesn't move. At 12:1, an app that stuffs documents into every prompt, the upgrade saves 10%. At 2:1, an app that writes long answers to short questions, it costs 6.7% more.
There is a second multiplier the price list doesn't show. Newer models often write more for the same task: longer answers, or reasoning tokens, hidden "thinking" text the model produces before answering and bills as output even though you never see it. The price per token can fall while the tokens per task grow.
For the Sonnet upgrade I computed the margin: on this workload, claude-sonnet-5.5 stays cheaper than claude-sonnet-4-5 until its output doubles. That sounds like plenty of room. With reasoning switched on, it isn't always.
Check before you bump
Before changing a model ID, put both price pairs and your real monthly token counts into a few lines of arithmetic. Your counts are in the usage field of every API response, or on your provider's billing dashboard.
def monthly(in_m, out_m, price_in, price_out):
return in_m * price_in + out_m * price_out
# your traffic, millions of tokens per month
IN_M, OUT_M = 20, 4
# expected output growth on the new model: 1.0 = same, 1.5 = 50% more
OUT_GROWTH = 1.5
old = monthly(IN_M, OUT_M, 0.30, 2.50) # gemini-2.5-flash
new = monthly(IN_M, OUT_M * OUT_GROWTH, 1.50, 9.00) # gemini-3.5-flash
print(f"${old:.2f} -> ${new:.2f} ({(new - old) / old:+.0%})")
This prints $16.00 -> $84.00 (+425%). The 1.5 is a guess, so replace it with a measurement: send the same few hundred real requests to both models and compare the output token totals. That measured ratio is the number worth trusting.
Upgrades usually come with a good reason, like better answers or a deprecation notice for the old model. The point isn't to avoid them. It's to know what the upgrade costs before the invoice tells you.
What this doesn't solve
This compares price, not quality. A pricier model that gets the task right on the first try can beat a cheap one you have to call three times, and I haven't measured that here. The table also uses list prices. Resellers price below list, and not always by the same percentage across versions: in our own catalog claude-opus-4-5 is 25% off and claude-opus-5.5 is 15% off, so at our prices that upgrade saves 9%, not 20%. Compare the prices you actually pay.
The takeaway
A new model ID is a new price list. Before you change the string, multiply your own token counts by both price pairs, then measure how many output tokens the new model actually writes.













