Skip to content

Provider announced a model deprecation

Providers retire old models regularly, and they announce it in a changelog, by email, or via a flag in /models. If you hardcoded gpt-4-0613 or claude-3-sonnet-20240229, the shutdown date is the date your production suddenly starts returning model_not_found. A push a few weeks in advance turns an outage into a calm migration task.

The pattern is a scheduled YC function that once a day compares the provider’s model list against your hardcoded ids.

Skeleton: poll /models and reconcile with your ids

Section titled “Skeleton: poll /models and reconcile with your ids”

The key fields are named differently across providers, but the idea is the same: a model has a deprecation flag/date. A state file keeps the alerts already sent.

import os, json, requests
STATE = "/tmp/model-deprecation.json"
# models you actually call in production
MODELS_IN_USE = {
"gpt-4o-2024-05-13",
"gpt-4-0613",
}
def notify(title, msg, prio):
requests.post(f"{os.environ['NOTIFLY_URL']}/message",
params={"token": os.environ["NOTIFLY_TOKEN"]},
json={"title": title, "message": msg, "priority": prio},
timeout=5)
def list_models():
r = requests.get("https://api.openai.com/v1/models",
headers={"Authorization": f"Bearer {os.environ['PROVIDER_KEY']}"},
timeout=15)
r.raise_for_status()
return {m["id"]: m for m in r.json()["data"]}
def handler(event, context):
catalog = list_models()
state = json.load(open(STATE)) if os.path.exists(STATE) else {}
changed = False
for mid in MODELS_IN_USE:
meta = catalog.get(mid)
# 1) the model disappeared from the catalog = already retired
if meta is None:
if state.get(mid) != "gone":
notify("🗑️ Модель исчезла из каталога",
f"{mid} больше нет в /models — вероятно, уже отключена. "
f"Прод может отдавать model_not_found.",
prio=9)
state[mid] = "gone"; changed = True
continue
# 2) the model is marked deprecated / has a shutdown date
dep = meta.get("deprecation") or meta.get("deprecated")
if dep and state.get(mid) != "deprecated":
when = meta.get("shutdown_date") or meta.get("sunset") or "дата не указана"
notify("⚠️ Модель помечена deprecated",
f"{mid} будет отключена: {when}.\n"
f"Пора выбрать замену и прогнать eval на новой модели.",
prio=7)
state[mid] = "deprecated"; changed = True
if changed:
json.dump(state, open(STATE, "w"))
return {"statusCode": 200, "body": json.dumps({"checked": list(MODELS_IN_USE)})}

priority=7 for deprecated (you have time), but priority=9 if the model has already disappeared from the catalog — that is almost an incident.

A once-a-day timer is more than enough:

Окно терминала
yc serverless trigger create timer \
--name notifly-model-deprecation \
--cron-expression '0 9 * * ? *' \
--invoke-function-name notifly-model-deprecation \
--invoke-function-service-account-id <sa-id>

Not everyone has deprecation in /models. In that case:

  • changelog page — download the HTML/RSS once a day, compare the hash, and on a change send a push (see the pattern from integrity-check);
  • announcement emails — wrap the provider’s newsletter address in an Email Inbox and alert on the words deprecat / sunset / retire in the subject;
  • runtime detection — catch model_not_found / invalid model right in production and send priority=10: it is the last line of defence, but better late than silent.
  • the model id and where you use it (service/file);
  • the shutdown date — the most important part, migration is planned around it;
  • the recommended replacement, if the provider names one;
  • a link to the provider’s changelog/migration guide.