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 productionMODELS_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>Providers without a flag in the API
Section titled “Providers without a flag in the API”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/retirein the subject; - runtime detection — catch
model_not_found/invalid modelright in production and sendpriority=10: it is the last line of defence, but better late than silent.
What to put in the alert text
Section titled “What to put in the alert text”- 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.