Blog ·

OpenAI is ending fine-tuning. What to do with your JSONL

On 7 May 2026, OpenAI told developers it is winding down self-serve fine-tuning. If your product runs on an ft:gpt-4.1-mini model, you have until 6 January 2027 to train anything new on OpenAI. After that date, nobody can start a fine-tuning job there.

Below are the dates, what happens to the models you already trained, and what to do with the one asset you can take with you, your training file.

The timeline

OpenAI closed the door in three steps (deprecations page):

Date Who loses the ability to create fine-tuning jobs
7 May 2026 Organisations that had never run a fine-tuning job
2 July 2026 Organisations with no inference on a fine-tuned model in the previous 60 days
6 January 2027 Everyone

Your existing fine-tuned models keep answering requests until OpenAI deprecates the base model they were trained on. Then they stop with it. Six legacy fine-tunes are scheduled to shut down on 23 October 2026, among them the fine-tunes of gpt-3.5-turbo, gpt-4, gpt-4.1-nano and o4-mini (deprecations).

gpt-4.1 and gpt-4.1-mini have no shutdown date yet. OpenAI promises at least six months' notice for generally available models (notice periods), so a fine-tune on those bases will probably run well into 2027. It will not get better, and you cannot retrain it after 6 January.

OpenAI is also shutting down its Evals platform (same page). It goes read-only on 31 October 2026 and closes on 30 November 2026. Teams that used Evals to check their fine-tunes lose the measuring tool in the same half-year as the training tool.

What you keep and what you lose

You never owned the weights. OpenAI gives you API access to a fine-tuned model by its ft: ID. The enterprise privacy page says custom models are yours alone to use. The API reference has no endpoint to export them.

You do own your training data. OpenAI keeps uploaded files until you delete them (your data guide). That JSONL is the result of the hard part of fine-tuning: someone chose the examples, cleaned them and wrote the right answers.

Download it now, before an account clean-up deletes it:

# list your fine-tuning files
curl https://api.openai.com/v1/files?purpose=fine-tune \
  -H "Authorization: Bearer $OPENAI_API_KEY"

# download one
curl https://api.openai.com/v1/files/file-abc123/content \
  -H "Authorization: Bearer $OPENAI_API_KEY" > training.jsonl

Each line should look like this, the chat format OpenAI has used since gpt-3.5-turbo (format guide):

{"messages": [
  {"role": "system", "content": "Route the ticket to one team."},
  {"role": "user", "content": "I was charged twice for October."},
  {"role": "assistant", "content": "billing"}
]}

Three ways forward

1. Go back to prompting. OpenAI's wind-down email, as quoted by Tessl, says newer base models follow instructions well enough that fewer teams need fine-tuning. For many tasks that is true. Put your best 20 examples in the prompt, test it on the rest, and compare. If a prompted GPT-6 Luna or Claude Haiku 5.5 matches your fine-tune, you are done and you have one fewer model to maintain.

It stops being true when you need the same answer format every time, at high volume, at the lowest cost per call. A prompt with 20 examples costs you those tokens on every request, and the model behind the prompt can change under you.

2. Fine-tune an open model yourself. You can rent GPUs, pick a base such as gpt-oss 20B or Qwen 3.5, run a LoRA training script and host the result. You get full control and the weights. You also get the GPU bill, the training code, the serving stack and the evaluation code, and someone has to keep all four working.

3. Move the JSONL to a managed service that trains open models. This is what we built Honed for. You upload the same file. Honed reads the messages format as it is, takes everything before the last assistant turn as the input and the last assistant turn as the answer, holds back a test set of at least 100 examples, and trains several open base models on the rest. When training ends, it runs the trained models on the held-out examples. It also runs the untrained base and the frontier models you pick on the same examples, and shows you the table.

On our support-routing run, the fine-tuned model got all 294 held-out tickets right. Claude Sonnet 5.5 got 95.9% and Claude Haiku 5.5 got 90.5% on the same tickets. With the lowest-cost goal, our runs took 13 to 26 minutes from upload to result.

What to check before you switch

Whatever you choose, run the new model and your current fine-tune on the same held-out examples before you move traffic. Three numbers decide it:

  • Accuracy on your own examples.
  • Cost per 1,000 calls, at your real input length.
  • Median latency, measured after the model is warm.

If the new model is not better on at least one of these and equal on the others, stay where you are until it is.

Then change three values in your client: base URL, key and model name. Honed serves an OpenAI-compatible endpoint, so your existing client keeps working:

import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://tryhoned.com/v1",
  apiKey: process.env.HONED_API_KEY,
});

const res = await client.chat.completions.create({
  model: "your-honed-model-id",
  messages: [{ role: "user", content: "I was charged twice for October." }],
});

Sources