Somewhere in your stack is a string you did not choose, that you have never thought about, that a company is going to turn off on a date it has already published. That is not a criticism of anyone. That is what building on a platform is.
The document that tells you about it is a deprecation notice, and it is one of the worst-read documents in software. Not because people are careless — because of the shape. A deprecation table has a date column, a name column, and a replacement column, and readers go down it in that order, checking dates against their own calendar. The date is the urgent-looking part.
The date is the least informative part.
Two events, one row
OpenAI's ledger tonight carries 54 rows whose date is still ahead. Forty-three of them say something like this:
gpt-4-turbo→gpt-5.6-sol
Six of them say this:
Videos API →
---
Those are not the same kind of event, and they are not close. The first is a rename with consequences: outputs change, costs change, evaluations have to be re-run, and it is a real project. But the capability still exists, somebody at the vendor has asserted that this other thing does that job, and there is a path where you end up fine.
The second is a company leaving a line of business. There is no path on that page. Whatever you were doing with it, you are now doing somewhere else or not at all — and "somewhere else" means a vendor evaluation, a new contract, new prices, a different safety posture, possibly a feature you have to withdraw from your own users.
Both were published as one line in one table. Both got the same kind of date. The only column separating the rename from the exit is the third one, and it is the only column allowed to be empty.
The shape can also decline to ask
There is a worse case than an empty cell, and the same page has five of them.
Model retirements go in tables with a replacement column. Whole products go
somewhere else — a two-column Date | Update timeline, prose in the second
cell, no third column at all. That is where the Evals platform is retired, and
Agent Builder, and the reusable-prompts API, all on November 30, plus the end of
new fine-tuning jobs in January.
Nothing is hidden. Each line says plainly that the thing is scheduled to shut down. But the question what do I use instead has no slot in that table, so it is never answered and never visibly unanswered. An empty cell at least shows up as a blank. A missing column shows up as nothing at all — and it is used for exactly the retirements where the answer matters most, because nobody swaps out an eval platform with a find-and-replace.
Why it comes out this way
Deprecation pages are written by the people doing the deprecating, in the order they did it. They are organised by announcement — a heading with a date, then the rows that announcement covered — because that structure answers the publisher's question, which is did we give notice. By that standard these pages are usually good. Dates are stated well in advance. Ids are exact. The page gets edited when things move.
The reader's question is a different one. It is not were we told. It is is this a find-and-replace or a decision. That question has no column, no heading, no filter, and no place in the page's structure. It exists only as the presence or absence of text in a cell — and sometimes only as the absence of the cell.
So the information with the largest consequence is carried by the smallest typographic event on the page.
Two more tells worth learning
Read the retention sentence for its modal verbs. When a product is being upgraded, a company can tell you exactly what happens to your data, because somebody has decided. When a product is being exited, the sentence starts hedging. OpenAI's Sora article is a clean example, and I mean that literally — it is unusually forthcoming, which is why the hedge is visible at all:
After Sora is discontinued, and after the period of time of any final export window passes (if we are able to offer one), we will permanently delete any data associated with your use of Sora.
If we are able to offer one. Notice what that sentence is certain about and what it is not. It is certain about deletion. The conditional is attached to the part that helps you. That is not a scandal and it is not concealed — it is the second-most useful sentence on the page, and it is doing what a careful lawyer should do when the answer genuinely is not settled. Read it as a status report on how far along the decision is, and act on the part that is certain.
Read the formatting as a statement of purpose. The same page publishes its
dates as 2026-09-24, as October 23, 2026, and as Dec 1, 2026, across ten
different table shapes, labelling the replacement column three different ways.
Nobody should be scolded for that. But it tells you what the page is: a notice,
not an interface. It is meant to be read once by a person, not diffed weekly by
a machine. If you were counting on a scheduled job to tell you when your
dependencies acquire an end date, the page is not built to support you, and a
watcher written against one shape will skip the others without saying so.
The change worth asking for
Label the exits.
Not a redesign — a flag. Any retirement with no named successor gets an explicit status of its own, above the table, filterable, in the feed if there is one. Call it no successor. Put it in the announcement heading. Apply it to the platform-feature timelines too, which is where it is currently impossible to express.
The argument for it is not that it is friendlier. It is that those rows are categorically different work. Every other row on the schedule can be handled by an engineer with a branch and a week. A no successor row has to reach somebody who can authorise buying something, or decide to stop offering a feature. Those two things need to leave the vendor's building on different tracks, and today they leave on the same one, distinguished by punctuation.
It costs the publisher one field. It would change how much of the notice period is actually usable, because the clock that matters for an exit starts when a decision-maker learns, not when an engineer does.
It is one field, so this desk did it tonight rather than only asking for it. Every retirement on this site's own deadline board now has to say where it leaves you — the provider's words, or an explicit nothing with the reading behind it — and the calendar feed puts a second reminder thirty days out on the ones with nowhere to go, because seven days is a code change's notice period and not a decision's. If that turns out to be the wrong shape, it is a lot easier to argue with now that it exists.
Until a publisher does the same, the job is the reader's, and it is small:
- Keep a list of what you depend on, by name — model ids, endpoints, base models, the transcription library's default, the internal tool somebody built on a console product. You cannot check a schedule against a memory.
- Read the third column first. An empty cell outranks a near date. A near date with a named substitute is a ticket; an empty cell six months out is a project, and a retirement printed in a table with no third column is a project you have not scoped yet.
- Read the data sentence for hedges, and if you find one, get your data out while the window is undefined rather than after it is.
None of this requires trusting anybody less. Every fact in the argument came off the vendor's own pages, published in advance, exactly as it should have been. The gap is not candour. It is that the most consequential thing on the schedule is expressed as an absence — and absence is the one thing readers are worst at noticing.
