Blog

gpt-4o, gpt-4o-mini and gpt-4.1 shut down on 14 January 2027: what breaks, what gpt-6-luna costs, and a test plan

Ramashankar S · · Updated · 15 min read

On Thursday, 14 January 2027, OpenAI switches off gpt-4o, gpt-4o-mini, gpt-4.1 and gpt-4.1-mini. Every dated snapshot behind those names goes too, along with every fine-tuned model built on one. OpenAI names a single replacement for all four: gpt-6-luna.

The notice went out on 14 October, 92 days ahead. That's about half the six months OpenAI's own policy promises for generally available models. From 28 October there are 78 days left, and a holiday code freeze can take two of those weeks.

The price is the easy part. gpt-6-luna lists at $0.10 / $0.50 per million tokens, a fraction of what gpt-4o and gpt-4.1 cost. The catch is that gpt-6-luna is a reasoning model and the four models it replaces aren't. Change only the model name and you can break function calling, get empty replies, and, if you're on gpt-4o-mini, lose most of the saving.

If you're here because of a 404 from one of the models shut down on 23 October, start with the post on those shutdowns.

Exactly what shuts down on 14 January

From OpenAI's deprecations page:

Model ID you callSnapshots that shut downOpenAI's replacement
gpt-4ogpt-4o-2024-08-06 (the default), gpt-4o-2024-11-20gpt-6-luna
gpt-4o-minigpt-4o-mini-2024-07-18gpt-6-luna
gpt-4.1gpt-4.1-2025-04-14gpt-6-luna
gpt-4.1-minigpt-4.1-mini-2025-04-14gpt-6-luna
Fine-tunes of any of theseSame day as the base modelNone that can be fine-tuned

gpt-4.1-nano and the May 2024 gpt-4o snapshot are already gone. They shut down on 23 October.

Not everything with "4o" in its name stops on the 14th. The audio and speech models run on their own schedules:

ModelShuts downOpenAI's replacement
gpt-4o-mini-tts6 Jan 2027gpt-realtime-2.1-mini
gpt-4o-audio, gpt-4o-mini-audio20 Jan 2027gpt-audio-1.5
gpt-4o-realtime20 Jan 2027gpt-realtime-2.1
gpt-4o-mini-realtime20 Jan 2027gpt-realtime-2.1-mini
gpt-4o-transcribe, gpt-4o-mini-transcribe, gpt-4o-transcribe-diarize26 Feb 2027gpt-live-transcribe or gpt-transcribe

gpt-6-luna can't stand in for any of those: it takes text and images, returns text, and doesn't support Realtime. chatgpt-4o-latest and the 4o search previews are already gone, and so is the Assistants API, shut down on 26 August 2026.

If you can't finish in time, the deprecations page says some developers may be able to provision dedicated capacity to keep a model after its shutdown date. That goes through OpenAI's sales team.

What gpt-6-luna costs next to each retiring model

Each retiring model's prices against gpt-6-luna, and how many reasoning tokens per request erase the saving

OpenAI's Standard prices per million tokens, for prompts up to 272K tokens:

ModelInputCached inputOutputBatch, input / output
gpt-4o$2.50$1.25$10.00$1.25 / $5.00
gpt-4o-mini$0.15$0.075$0.60$0.075 / $0.30
gpt-4.1$2.00$0.50$8.00$1.00 / $4.00
gpt-4.1-mini$0.40$0.10$1.60$0.20 / $0.80
gpt-6-luna$0.10$0.01$0.50$0.05 / $0.25
gpt-6.1-terra$1.00$0.05$5.00$0.50 / $2.50
gpt-6-sol$2.00$0.20$10.00$1.00 / $5.00

Two charges are new. Cache writes now cost money: $0.125 per million tokens on gpt-6-luna for the default 30-minute retention, 1.25x the input price. The old models charged nothing for writes. And a prompt over 272K input tokens is billed at 2x input and 1.5x output for the whole request, which is $0.20 / $0.75 on gpt-6-luna. gpt-4.1 charged one flat rate up to its 1M-token context.

Per token, moving off gpt-4o or gpt-4.1 cuts the price 16x to 25x. Off gpt-4.1-mini, roughly 3x to 4x. Off gpt-4o-mini, the cut is thin: a third off input and 17% off output.

That thin margin matters because reasoning tokens are billed as output, and gpt-6-luna reasons at medium effort unless you say otherwise. Take a job of 1,000 requests with 2,000 input and 500 visible output tokens each, no caching. This is how much hidden reasoning each move can absorb before gpt-6-luna stops saving money:

Moving fromJob on the old modelJob on gpt-6-luna, effort noneSaving ends at
gpt-4o$10.00$0.4519,100 reasoning tokens per request
gpt-4.1$8.00$0.4515,100 reasoning tokens per request
gpt-4.1-mini$1.60$0.452,300 reasoning tokens per request
gpt-4o-mini$0.60$0.45300 reasoning tokens per request

Three hundred tokens is one short paragraph of thinking. For gpt-4o-mini workloads, start at none and make your evals justify anything higher.

When gpt-6-luna isn't enough

OpenAI describes gpt-6-luna as its most efficient model for "focused, high-volume tasks". If you used gpt-4o or gpt-4.1 for harder work, such as long documents, multi-step tool use or writing that customers read, test one larger model next to it:

  • gpt-6.1-terra, released on 26 October, costs $1.00 / $5.00, still less than half of gpt-4o. It accepts none effort, but tool calling on it requires the Responses API.
  • gpt-6-sol costs $2.00 / $10.00, the same output price as gpt-4o. Like gpt-6-luna, it does function calling in Chat Completions only at none effort.
  • Avoid gpt-5, gpt-5-mini and gpt-5-nano, which shut down on 11 December, and gpt-5.1, which goes on 1 April 2027. gpt-5.6-terra still runs, but at $2.00 / $12.00 it costs 2x to 2.4x as much as gpt-6.1-terra.

For a side-by-side run of Luna and Sol on code, this is a useful reference:

GPT-6 Sol and GPT-6 Luna on 144 coding promptsAI Coding Daily · 14:06 · YouTube
gpt-6-sol and gpt-6-luna run against the same 144 coding prompts.

What breaks when you only change the model name

The old models answered straight away. gpt-6-luna thinks first, and most new errors come from that:

  • Reasoning is on by default at medium. Set reasoning_effort (Chat Completions) or reasoning.effort (Responses) to none for the behavior closest to gpt-4o, and raise it only where your evals show a gain.
  • Function calling through Chat Completions works on gpt-6-luna only with reasoning_effort set to none. For tools and reasoning together, OpenAI says to use the Responses API.
  • At any effort other than none, remove temperature, top_p and top_logprobs, plus logprobs in Chat Completions. A lot of gpt-4o code sets temperature=0 by habit.
  • max_tokens is deprecated in favor of max_completion_tokens, which counts reasoning tokens too. A cap of 300 that suited gpt-4o-mini can run out mid-reasoning and return empty content with finish_reason: "length". You still pay for the reasoning. OpenAI suggests leaving at least 25,000 tokens for reasoning and output while you experiment.
  • Predicted Outputs (the prediction parameter) is documented only for gpt-4o, gpt-4o-mini and the gpt-4.1 family. If a code-editing tool of yours relies on it, test whether it still works on gpt-6-luna before 14 January.
  • Prompt caching settings changed from GPT-5.6 on: prompt_cache_retention becomes prompt_cache_options.ttl, which defaults to "30m".

The specs side by side, from OpenAI's model pages:

gpt-4o, gpt-4o-minigpt-4.1, gpt-4.1-minigpt-6-luna
ReasoningNoNoYes, medium by default
Context window128,0001,047,5761,050,000 (922,000 max input)
Max output16,38432,768128,000, reasoning included
Tools in Chat CompletionsYesYesOnly at effort none
Predicted OutputsYesYesNot documented
Fine-tuningYesYesNo
Knowledge cutoffOct 2023Jun 2024May 2026

Rate limits won't hold you back: gpt-6-luna's are equal to or higher than all four old models' at every usage tier.

Images need a check of their own. OpenAI's newer models count image tokens in 32-pixel patches rather than gpt-4o's 512-pixel tiles, and its sizing table doesn't list gpt-6-luna yet, so measure prompt_tokens on a sample of your real images instead of estimating. OpenAI also fixed a bug that degraded image understanding in gpt-6-luna on 25 September. Rerun any image evals done before then.

The migration, in code

A typical gpt-4o-mini call with tools:

response = client.chat.completions.create(
    model="gpt-4o-mini",
    temperature=0,
    max_tokens=300,
    messages=messages,
    tools=tools,
)

The closest equivalent on gpt-6-luna, still on Chat Completions (OpenAI Python SDK 3.42):

from openai import OpenAI

client = OpenAI()
# messages and tools stay exactly as they were for gpt-4o-mini

response = client.chat.completions.create(
    model="gpt-6-luna",
    reasoning_effort="none",     # gpt-6-luna defaults to "medium"
    max_completion_tokens=300,   # replaces max_tokens and counts reasoning tokens
    messages=messages,
    tools=tools,                 # Chat Completions tools need reasoning_effort "none"
)

usage = response.usage
print("cached input:", usage.prompt_tokens_details.cached_tokens)
print("reasoning:", usage.completion_tokens_details.reasoning_tokens)

Log reasoning_tokens on every request during testing. It's the number that decides whether the move saves money.

If a job does better with some reasoning and also calls tools, move it to the Responses API. Function definitions lose their nested function object and are strict by default, response_format becomes text.format, and the model's output items, reasoning included, go back in with the tool result:

import json
from openai import OpenAI

client = OpenAI()

tools = [{
    "type": "function",
    "name": "get_order_status",
    "description": "Look up the shipping status of an order.",
    "parameters": {
        "type": "object",
        "properties": {"order_id": {"type": "string"}},
        "required": ["order_id"],
        "additionalProperties": False,
    },
}]

def get_order_status(order_id):
    return {"order_id": order_id, "status": "shipped"}  # your real lookup here

history = [{"role": "user", "content": "Where is order 8812?"}]
response = client.responses.create(
    model="gpt-6-luna", reasoning={"effort": "low"}, tools=tools, input=history
)

history += response.output
for item in response.output:
    if item.type == "function_call" and item.name == "get_order_status":
        result = get_order_status(**json.loads(item.arguments))
        history.append({
            "type": "function_call_output",
            "call_id": item.call_id,
            "output": json.dumps(result),
        })

response = client.responses.create(
    model="gpt-6-luna", reasoning={"effort": "low"}, tools=tools, input=history
)
print(response.output_text)

Fine-tuned models have no successor

Fine-tunes follow their base model, so every fine-tuned gpt-4o, gpt-4o-mini, gpt-4.1 and gpt-4.1-mini model stops answering on 14 January. Retraining isn't the way out:

  • OpenAI is winding down its fine-tuning platform. Existing customers can create training jobs until 6 January 2027.
  • The supervised fine-tuning guide lists only the gpt-4.1, gpt-4.1-mini and gpt-4.1-nano snapshots as trainable, and all three are gone by 14 January.
  • gpt-6-luna's model page marks fine-tuning as not supported.

The practical replacement is the base model with your training data moved into the prompt. Put a few dozen of your best training examples into a fixed system prompt at the very start, so they're cached, and use the rest of the set as an eval. Score gpt-6-luna against the fine-tune's own outputs while the fine-tune still runs.

The numbers help. Fine-tuned gpt-4o costs $3.75 / $15.00 per million tokens and fine-tuned gpt-4o-mini $0.30 / $1.20. On gpt-6-luna, a long cached prefix costs $0.01 per million tokens to read, plus $0.125 per million each time the cache is written.

Find every caller first

Start with the list of models your key can reach. This prints every gpt-4o and gpt-4.1 model, fine-tunes included, with its shutdown_date where OpenAI has set one:

curl -s https://api.openai.com/v1/models \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  | jq -r '.data[] | select(.id | test("gpt-4o|gpt-4\\.1")) | "\(.shutdown_date // "no date")  \(.id)"' | sort

A fine-tune may show no date. It still stops with its base model.

Then find out who calls them. The Usage API, which needs an admin key, totals requests by model and by API key. This covers 1 to 31 October (1790812800 is 1 October in Unix time) and prints one line per model and key:

curl -s "https://api.openai.com/v1/organization/usage/completions?start_time=1790812800&bucket_width=1d&limit=31&group_by=model&group_by=api_key_id" \
  -H "Authorization: Bearer $OPENAI_ADMIN_KEY" \
  | jq -r '[.data[].results[] | select(.model // "" | test("gpt-4o|gpt-4\\.1"))]
      | group_by([.model, .api_key_id])[]
      | "\(map(.num_model_requests) | add)  \(.[0].model)  \(.[0].api_key_id)"'

If the response has has_more: true, call it again with page set to next_page.

Code search misses batch input files, env files and notebooks. The 23 October post covers where to look. Saved prompt objects (pmpt_...) break even earlier: OpenAI shuts down the v1/prompts API on 30 November, whichever model a prompt points to.

Finally, rehearse the shutdown. OpenAI project model permissions accept a deny list, so block the four models in a staging project for a day and fix whatever fails.

A test plan to finish before 14 January

Countdown to 14 January 2027: OpenAI shutdown dates and a suggested plan
  1. Run the two checks above and list every job, API key and model ID, including fine-tunes.
  2. Save a baseline now: send 200 to 500 real requests per job to the current model and store the outputs. After 14 January you can't regenerate them.
  3. Pick candidates per job: gpt-6-luna for everything, plus gpt-6.1-terra or gpt-6-sol for work that used gpt-4o or gpt-4.1 because it was hard.
  4. Run the baseline set at reasoning_effort: "none", then at low, score both the same way, and keep the lowest setting that matches the old model.
  5. Fix the parameters listed under "What breaks" above.
  6. Check that every JSON schema and function argument still parses.
  7. Count image tokens on real files, and flag prompts over 272K tokens (2x input, 1.5x output price) or 922,000 (they won't fit).
  8. Price the result from the usage object: reasoning tokens, cached tokens and cache writes.
  9. Measure p50 and p95 latency at the chosen effort.
  10. Rehearse the shutdown with a deny list in staging.
  11. Ship behind a config setting with a tested fallback model, and move traffic in steps.
  12. Delete the old IDs, and add a CI check that fails when any model you call gets a shutdown_date.

On Azure OpenAI: April, not January

Azure runs its own schedule. Microsoft's retirement page gives these models three more months:

Azure OpenAI modelVersionRetiresMicrosoft's replacement
gpt-4o2024-08-06, 2024-11-2014 Apr 2027gpt-5.1
gpt-4o-mini2024-07-1814 Apr 2027None listed
gpt-4.12025-04-1414 Apr 2027None listed
gpt-4.1-mini2025-04-1414 Apr 2027None listed
gpt-4o2024-05-1314 Jan 2027gpt-5.1 (2025-11-13)

The last row is the one Azure date on 14 January. Global Standard and Data Zone Standard deployments of that version upgrade to gpt-5.1 automatically; provisioned ones don't.

On Azure, fine-tuned deployments last until 1 October 2027 for gpt-4o and gpt-4o-mini, and 14 October 2027 for gpt-4.1 and gpt-4.1-mini.

Two cautions. Microsoft's suggested replacement, gpt-5.1, itself retires on Azure on 13 July 2027. And the page was last updated on 23 September, before OpenAI's notice, so check it again before you plan around April. gpt-6-luna is already generally available in Microsoft's Foundry catalog.

Where Aight fits

Aight is one OpenAI-compatible API for 126 models from OpenAI, Anthropic, Google, xAI, DeepSeek and others. gpt-4o, gpt-4.1 and gpt-4.1-mini are on its models page at OpenAI's list prices: $2.50 / $10.00, $2.00 / $8.00 and $0.40 / $1.60. gpt-4o-mini isn't listed. The models page shows Azure as the host for these models, and Azure's dates (above) run later than OpenAI's, but Aight hasn't set a retirement date for them yet, so don't plan around April. Aight gives at least 14 days' notice before it removes a model, where the provider allows, with a named replacement.

gpt-6-luna is on Aight at the same $0.10 / $0.50 ($0.20 / $0.75 above 272K tokens), cached input $0.01, cache writes $0.125. Counting the 3% processing fee and the 10% extra on every recharge, that's about $0.094 / $0.47. The same key reaches gpt-6-sol, Claude and Gemini, so you can run your baseline set against several candidates on one key and one balance.

Here's where going direct is the better choice:

  • If your gpt-4o work runs through the Batch API, OpenAI's Batch price for gpt-6-luna is $0.05 / $0.25, half the Standard rate. Aight documents chat completions, embeddings and the model list only. The post on the cheapest way to use the OpenAI API covers Batch and the other discounts.
  • If you need tools and reasoning together on gpt-6-luna, that's the Responses API, so call OpenAI directly.
  • gpt-6.1-terra isn't on Aight.

Aight's API reference documents model, messages and stream for chat completions. Before you move volume, send a test request with reasoning_effort set to none and check reasoning_tokens in the usage block. Check each model's context window and maximum output on the models page too, since they can differ from OpenAI's figures.

Switching an existing OpenAI client is two lines:

import os
from openai import OpenAI

client = OpenAI(
    base_url="https://api.getaight.ai/v1",
    api_key=os.environ["AIGHT_API_KEY"],
)

Each Aight key also takes a list of allowed models. Take gpt-4o and gpt-4.1 off a key's list once a service has moved, and any caller you missed gets a 403 now rather than an outage later.

The model name is the quick part. Book the eval time now, while the old models are still there to compare against.


Sources

Checked on 31 October 2026.