The API deprecation notice template: sunsetting a version without breaking customers
Every API deprecation is a promise you are allowed to break exactly once — and only if you tell everyone before you do. Small teams usually fail at this in one of two ways: they never deprecate anything (versions pile up, every bug exists in four places at once), or they deprecate with a changelog entry nobody reads and a deadline nobody believed. The outage email templates handle the incident you didn't plan; this template handles the breakage you did. The honest version has three notices, one timeline, and a holdout ladder driven by actual usage, not by who replied to your email.
1. The three notices (one message, three channels)
A deprecation is communicated three times because each channel reaches a different person:
| Channel | Reaches | When |
|---|---|---|
| The changelog entry — what is deprecated, the sunset date, the replacement, the migration note | People who read changelogs (your best integrators already do) | T−90 days, and linked from every affected endpoint's docs page |
The runtime warning — the Deprecation and Sunset headers (and Link to the docs) on every deprecated response | The code and the person watching logs — it reaches customers who never read anything you send | T−90 through T−0, on every request to the old version |
| The direct email — sent only to accounts that called the old version in the last 30 days | The owner of the integration, with a name attached | T−60, and again at T−30 only to accounts still calling |
The runtime header is the one small teams skip and the one that saves you: a warning that appears in the customer's own logs cannot be missed by the person whose code will break. One line of middleware — Deprecation: true, Sunset: <date> — is worth fifty emails.
2. The sunset timeline
| Clock | What happens | Gate to pass |
|---|---|---|
| T−90 | Changelog + docs banner + runtime headers live; first email to recent callers | The replacement must already exist and be documented. Deprecating before the replacement works is breaking, not deprecating |
| T−60 | Usage dashboard reviewed: who is still calling? Migration guide published with copy-paste diffs | Every holdout has a named owner on your side tracking their switch |
| T−30 | Second email to remaining callers, now with their own usage counts in the body ("your account made 41,000 calls to v1 last week") | Offer the 15-minute migration call to anyone still stuck |
| T−7 | Final notice; write the fallback decision: hard-stop, or read-only grace window | Grace window is a decision made now, not improvised at sunset |
| T−0 | Sunset: the endpoint returns 410 Gone with a JSON body naming the replacement — never a naked 404 | Sunset-day monitoring of 410s, so a spike means someone needs help, not silence |
| T+7 | Deprecation review: who migrated, how long it took them, what the next timeline should be | The review writes the next version's habits |
Ninety days is the small-team standard: long enough for a customer's own release cycle to absorb the change, short enough that the old version does not become permanent. If a customer's migration genuinely cannot land in ninety days, the exception is a documented extension with a new date — never a quiet indefinite extension, which is how dead versions survive forever.
3. The direct email: what it must contain
Five sentences, all of them specific, none of them marketing:
- What is going away — the exact version and endpoints, not "some legacy endpoints."
- When — one calendar date. "Early next quarter" is not a date; it is a shrug.
- Why — one honest sentence (security patching, a bugfix that cannot ship to the old version, consolidation). Customers accept reasons; they do not accept silence.
- What to do — the replacement endpoint and the migration guide link, with the diff between old and new shown, not described.
- A human to reply to — a named engineer's address. "Reply to this email" counts if a person actually reads it.
The subject line that works: "Action needed: v1 API sunsets March 31 — your migration guide." The two that don't: anything starting "We're excited to announce…" and anything burying the date below the fold.
4. The holdout ladder
Usage data, not email opens, decides the escalation:
- Week 1 of sunset-minus-30: list every account still calling. Rank by call volume. The ten loudest are your whole problem — migrate them personally.
- Long-tail silence: accounts making 3 calls a month are usually forgotten cron jobs, not customers. The migration guide link in the 410 body is their fix.
- The zero-warning rule: never let T−0 arrive for an account that never received a runtime header or a direct email. If your comms missed them, that is your incident, not their fault — extend their window and say so.
This is the same discipline as the invoice collection ladder: rank by exposure, escalate by evidence, and never treat the list as one blob.
5. Versioning habits that make the next deprecation boring
- Date or number your versions in the path or header —
/v2/orX-API-Version. "Current" and "legacy" as version names mean every sunset is undefined. - Ship the
Deprecation/Sunsetheaders from the day a version is superseded — not the week before the deadline. - Keep the migration guide alive after sunset. Integrators arrive at the 410 for months; the guide is part of the endpoint's grave marker.
- Announce the replacement's release separately — a launch note and a deprecation note are different messages with different audiences.
- Log every deprecation's holdout curve — it calibrates the next timeline better than any rule of thumb.
6. Common mistakes
- Announcing in the changelog only. A changelog entry is a legal fig leaf, not a communication. Customers who never read it will call the 410 an outage — and to them, it is one.
- Deprecating before the replacement is live. "Migrate to v2" with no v2 documentation is a shutdown, not a migration.
- The naked 404 at sunset. A
410 Gonewith a JSON body pointing at the replacement turns your sunset into their error handling; a 404 turns it into a support ticket and a tweet. - "Early next quarter" instead of a date. Dates are commitments; seasons are excuses. The SLO template rule applies: numbers or nothing.
- Sunset-day silence. Watching 410 counts on sunset day is the difference between "three forgotten crons need help" and "a customer churned and we read about it in a review."
Takeaways
- Three notices, one message. Changelog for readers, runtime headers for machines, direct email for owners — the header reaches people no email ever will.
- Usage data runs the ladder. Rank holdouts by real call volume; the loudest ten are the migration.
- Sunset loudly. 410 with a body, not 404; watch the 410s on the day; the deprecation review writes the next version's habits.
From the HIVE80lab kit
- The First 30 Minutes — free incident quick-start
- Ops Starter Kit — incident response for small teams — $14
- Ops Starter Kit Vol. 2 — advanced incident response & communications — $27
- Ops Mega Bundle — all 5 kits in one download — $49
Related: the leaked API key runbook covers the rotation you hope never to run, the changelog automation keeps the deprecation entry from living in someone's drafts, and the vendor outage runbook is the mirror image — what you want from a vendor who is sunsetting something you depend on.