# Your Codex model shuts off July 23 — a 7-day migration map

> Source: <https://dev.to/amdmsz/your-codex-model-shuts-off-july-23-a-7-day-migration-map-nm8>
> Published: 2026-07-15 21:19:25+00:00

I pin model IDs on purpose. Floating aliases have burned me before — a silent swap under a `-latest`

tag once changed a tool-calling detail in production and cost me a Saturday with `git bisect`

and a coffee I didn't enjoy. So everything I run points at a dated snapshot. `gpt-5-codex`

was one of them.

Last week I finally read OpenAI's deprecations page top to bottom instead of skimming it, and there it was: `gpt-5-codex`

, retiring **2026-07-23**, sitting quietly next to ten of its neighbors. As I write this it's July 16. That's **seven days**.

If you pinned any of the snapshots below, consider this your heads-up. Here's the full retirement list, how to find out in about ten minutes whether you're exposed, the replacement map with the things I'd actually regression-test, and the one structural change that turned my last forced migration from scary into boring.

Straight from OpenAI's [API deprecations page](https://developers.openai.com/api/docs/deprecations). I checked each row against the source while writing this — do the same before you act on it, because dates and replacements do get revised.

| Retiring model | OpenAI's suggested replacement |
|---|---|
`gpt-5-codex` |
`gpt-5.5` |
`gpt-5.1-codex` |
`gpt-5.5` |
`gpt-5.1-codex-max` |
`gpt-5.5` |
`gpt-5.1-codex-mini` |
`gpt-5.4-mini` |
`gpt-5.2-codex` |
`gpt-5.5` |
`gpt-5-chat-latest` |
`gpt-5.5` |
`gpt-5.1-chat-latest` |
`gpt-5.5` |
`gpt-4o-search-preview-2025-03-11` |
`gpt-5.4-mini` |
`gpt-4o-mini-search-preview-2025-03-11` |
`gpt-5.4-mini` |
`gpt-4o-mini-tts-2025-03-20` |
`gpt-4o-mini-tts-2025-12-15` |
`computer-use-preview-2025-03-11` |
`computer-use-preview` (or `gpt-5.4-mini` ) |

Note the shape of it: the `*-codex`

line collapses into `gpt-5.5`

— except `gpt-5.1-codex-mini`

, which drops to `gpt-5.4-mini`

— the `chat-latest`

aliases fold into `gpt-5.5`

too, the two `*-search-preview`

snapshots move to `gpt-5.4-mini`

, and the two preview families (`tts`

, `computer-use`

) just roll to a newer dated snapshot / the undated alias. Once you see the buckets, the migration is less intimidating than the eleven-row table looks.

The trap isn't the model IDs you remember hardcoding. It's the ones you forgot — buried in an `.env`

, a config table, a feature flag, a notebook a teammate ran once. Two passes catch almost all of it.

**1. Grep the code.** One regex covers every retiring ID:

```
grep -rniE \
  'gpt-5-codex|gpt-5\.1-codex|gpt-5\.2-codex|gpt-5(\.1)?-chat-latest|gpt-4o(-mini)?-search-preview-2025-03-11|gpt-4o-mini-tts-2025-03-20|computer-use-preview-2025-03-11' \
  --include='*.py' --include='*.ts' --include='*.js' --include='*.go' \
  --include='*.rb' --include='*.java' --include='*.env*' --include='*.y*ml' \
  --include='*.json' --include='*.toml' .
```

**2. Grep what you actually shipped.** Code search misses IDs that arrive from a database, a dashboard toggle, or a user-supplied param. If you log outbound requests as JSON lines with a `.model`

field, count what really went over the wire:

```
jq -r 'select(.model) | .model' requests.log \
  | sort | uniq -c | sort -rn \
  | grep -E 'codex|chat-latest|search-preview-2025-03-11|gpt-4o-mini-tts-2025-03-20|computer-use-preview-2025-03-11'
```

No structured logs? OpenAI's usage export / dashboard breaks spend down by model — sort by name and look for the eleven above. If a retiring ID shows up there but not in your grep, that's exactly the config-driven caller you'd have missed.

Keep the retiring set around as a constant; it's handy in a CI check that fails a build if any of these strings reappears:

```
RETIRING_2026_07_23 = {
    "gpt-5-codex", "gpt-5.1-codex", "gpt-5.1-codex-max", "gpt-5.1-codex-mini",
    "gpt-5.2-codex", "gpt-5-chat-latest", "gpt-5.1-chat-latest",
    "gpt-4o-search-preview-2025-03-11", "gpt-4o-mini-search-preview-2025-03-11",
    "gpt-4o-mini-tts-2025-03-20", "computer-use-preview-2025-03-11",
}
```

Swapping a string is the easy part. The replacements are not drop-in twins, so treat each bucket as a behavior change, not a rename.

`*-codex`

→ `gpt-5.5`

.`gpt-5.5`

is a general model. Re-run your coding evals / golden transcripts and watch reasoning depth, patch/diff formatting, and tool-call arguments. If you parse the model's output with anything stricter than "trust me," diff old vs. new on a real sample before you flip prod.`gpt-5.1-codex-mini`

→ `gpt-5.4-mini`

.`gpt-5(.1)-chat-latest`

→ `gpt-5.5`

.`*-search-preview-2025-03-11`

→ `gpt-5.4-mini`

.`gpt-5.4-mini`

may not ground the same way, so verify the capability you relied on still exists — and if you need live retrieval, wire up the web-search tool on the Responses API rather than assuming the base model does it for you.`gpt-4o-mini-tts-2025-03-20`

→ `gpt-4o-mini-tts-2025-12-15`

.`computer-use-preview-2025-03-11`

→ `computer-use-preview`

.My minimum regression checklist before flipping any of these in production:

While you're in the deprecations page, scroll down. A second batch — `gpt-5-2025-08-07`

, `gpt-5-mini`

, `gpt-5-nano`

, `gpt-5-pro`

, `o3`

, and `o3-pro`

— is slated to retire **2026-12-11**, moving to `gpt-5.5`

/ `gpt-5.4-mini`

/ `gpt-5.4-nano`

/ `gpt-5.5-pro`

. Not urgent this week, but if you're touching model config anyway, note it now so December isn't a second scramble.

Here's the part I keep relearning. The pain of a forced migration scales with **how many places name the model**. When `gpt-5-codex`

is a literal string in nineteen files, three services, and a config table, a deprecation is a nineteen-file PR under a deadline. When the model name lives in exactly one routing/config layer, it's a one-line change and a redeploy.

So my rule now: application code never spells a model ID. It asks for a *role* — `"code-agent"`

, `"cheap-classifier"`

, `"tts"`

— and a small config maps that role to the concrete snapshot. A forced migration becomes editing that map, re-running evals, shipping. The eleven models above would have been one commit.

In my own setup that routing layer is [byesu](https://docs.byesu.com/en/guide/openai-codex-migration-2026), an OpenAI-compatible gateway where a single key fronts `gpt-5.5`

/`gpt-5.6`

alongside Claude, Gemini, and Grok. Because it's OpenAI-compatible, the replacement models in that table are reachable by pointing my existing client at one base URL and changing the model string in one place — the SDK, request shape, and parsing code don't move. You don't need a gateway to get this benefit, to be clear; a plain constants file or a `MODEL_ROLES`

dict buys you most of it. The point is the indirection, not the tool. But having every provider behind one compatible endpoint is what let me treat "gpt-5-codex is gone" as a config edit instead of a cross-repo hunt.

Concretely, before July 23: run the two greps, list your exposed snapshots, pick the replacement per the table, diff outputs on real traffic, and ship. If you've got the eleven strings scattered across the codebase, this is also the cheap moment to pull them behind one role→model map — because December's batch is already scheduled, and there will always be another one after that.

Go read the [source page](https://developers.openai.com/api/docs/deprecations) yourself and check the dates against your own stack. Deprecation tables are the one kind of doc where "I'll get to it next sprint" has a hard cutoff.

If you pinned `gpt-5-codex`

like I did — the clock's already running.
