Model retirement is not an accident: turning deprecation into a scheduled task

Pitfalls Published 2026-10-19 72 views API Compass
You open your laptop, get 404 model_not_found, and production is down. It is almost always an upstream retirement, not an outage. Three layers of propagation, four questions to ask, six checks, one rollout plan.

A typical morning

07:40. Monitoring fires: the core endpoint is returning 500. One line in the log:

{"error":{"message":"model_not_found","type":"invalid_request_error"}}

It worked yesterday. You did not change the code, upgrade the SDK or rotate the key. The only thing that changed is that the upstream retired that model.

This happens several times a year in every team, and it never needs to happen at all — because a retirement is never a surprise. The vendor publishes a notice ahead of time, the relay receives it, and nobody turns it into a ticket in your backlog.

Retirement propagates through three layers

Layer one: vendor deprecation

Major vendors give notice: Anthropic, OpenAI and Google usually maintain a deprecations page with three to twelve months of lead time. Chinese vendors tend to be shorter, commonly one to three months.

The defining feature of this layer: the information is public, but you will not go looking for it.

Layer two: the relay removes the route

Once the vendor retires a model, the entry disappears from the relay's model list. The problem is that three common behaviours differ enormously:

  • Some announce it in advance, some simply vanish;
  • Some keep the old model name and silently forward to the new model — good for you, except you do not know the output changed;
  • Some keep the name and return 404 without telling you what replaced it.

Which of these three you get decides whether your code breaks.

Layer three: the model name hardcoded in your code

resp = client.chat.completions.create(model="claude-sonnet-5", ...)

This line is the last line of defence, and the only layer you fully control.

Inventory your own model names first

Before discussing migration, answer a basic question: how many model names does your project contain, and in which files?

# adjust the pattern to your naming convention
grep -rhoE '"(gpt|claude|gemini|qwen|glm|kimi|deepseek|grok|doubao)[a-zA-Z0-9._-]*"' \
  --include=*.py --include=*.ts --include=*.js --include=*.go . \
  | sort | uniq -c | sort -rn

You will usually get a longer list than expected — test files, comments, CI configuration, and a script left behind by someone who has since left the team.

Then give every entry four fields:

Current nameUsed forReplacementLatest switch dateStatus
claude-sonnet-5main chatclaude-sonnet-5.52027-03-01evaluating
gpt-5.6-lunasummariesgpt-5.6-luna-22026-12-15switched

This table needs no tooling; a Markdown file is enough. Its value is not that it looks tidy, but that next time you get a 404 you have something to look up.

Four questions for the relay

  1. Will you notify before retirement, and through which channel? Email, site notice, API, or not at all.
  2. How long does the old name survive? Immediate 404, or forwarding to the replacement for a while.
  3. Do you offer aliases? Names like claude-sonnet-latest without a minor version. With an alias you do not touch code when the vendor moves a minor version.
  4. Can I still query historical usage afterwards? Needed for reconciliation and cost retrospection.

Question three has the best return. An alias removes most of the migration work — provided you verify it really follows upstream instead of pointing at one frozen version. The test is easy: record the model identifier the alias currently reports (most APIs include a model field in the response), check again two weeks later, and if it changed, it is following.

Migration is not a rename

This is the most underestimated step. After switching models, six things can change:

What changesHow it shows upHow to check
Output formatNew thinking or reasoning fields, different tool-call structureRun a fixed test set and diff the structure
max_tokens ceilingLower on the new model, long output truncatedRequest one very long output and read finish_reason
Context lengthShorter on the new model, long documents return 400Run your longest real input once
PriceUnit price moves, the bill may doubleCompare with the official list and cost one typical request
LatencyThe new model is slower, timeouts need retuningSingle-worker P95
Refusal tendencySafety policy changed, prompts that used to pass are rejectedRun real production samples

Of these six, only price and latency are caught by ordinary monitoring. The other four surface slowly as "occasional failures" and "shorter output" unless you test for them.

Shadow rollout: spread the risk over a week

Do not switch everything at once. A workable order:

  1. Shadow mode: send the same inputs to the new model and only record the results. Run three days and compare divergence.
  2. Small traffic: route 5% to the new model, watch error rate and latency.
  3. Switch by scenario: low-risk surfaces first (summaries, classification), core chat last.
  4. Keep a rollback switch: the model name must be configurable, never hardcoded. This is the precondition for everything above.

How to compute divergence in step 1: take 200 real inputs, run both models, and manually review 20 pairs. Do not switch above a 15% divergence rate — first establish whether the difference is "better" or "off target".

Summary

  1. A retirement is not an outage; it is a notice nobody turned into a ticket.
  2. It propagates through vendor, relay and your code, and any layer without a plan breaks.
  3. Inventory the model names in your code into a table with a latest-switch date.
  4. Prefer aliases, but verify they really track upstream instead of being pinned.
  5. Six things need checking in a migration; ordinary monitoring covers two.
  6. The minimum viable rollout is three days of shadow mode plus 5% traffic, with a rollback switch as the precondition.

Was this useful? If you have run into something the article does not cover, tell us and we will verify it and update the text.

Related articles

RPM, TPM and concurrency: the four real shapes of relay rate limiting, and how to find the true ceiling

2026-10-19

Three traps in choosing a site from a leaderboard alone

2026-10-07

Evening peak jitter: upstream, network path, or your own concurrency

2026-10-07

Four ways to check a "direct official connection" or "pure resale" claim

2026-10-06

A 30-minute emergency checklist after an API key leak

2026-10-05

Five terms to check before topping up: balance, refunds and expiry, question by question

2026-10-04

Read on: a few of the services we list

This article does not point at a specific model family, so here are a few of the highest-scoring services we list, in case you want to read on. They are ordered by score and uptime and are not a recommendation.

See the full list in the directory, or browse by model family.