How to Sunset an API Version Without Breaking Customers
Every API eventually needs to remove something: a field, an endpoint, an entire version. The technical part is usually trivial. The hard part is that someone, somewhere, is still calling the old version, and they don't find out it's going away until it already has.
A deprecation that goes well looks boring from the outside: nobody notices, because everyone who needed to move already did.
Announce the sunset before you build the replacement
Tell integrators a version is being retired as early as you reasonably can, ideally before the replacement even ships, so the timeline for migration isn't compressed by how long the new version took to build. A deprecation notice that arrives the same week as the shutdown isn't a notice, it's an outage with advance warning.
Put the sunset date in the documentation itself, not just in an email that might get filtered or missed by whoever's inbox it landed in a year ago. A deprecation header on every response from the old version, naming the date it stops working, reaches even the integrator whose team has turned over twice since they first wired up the integration.
Version in the URL or the header, and pick one
URL versioning, like /v2/orders, makes it obvious at a glance which version a given call is using, which makes tracking usage far simpler later. Header versioning is less visible in logs and harder to grep for across a year of traffic. Whichever you pick, consistency across your whole API matters more than which one you chose, since a mix of both makes usage tracking meaningfully harder.
Whatever scheme you settle on, write down the rule for what counts as a breaking change versus what doesn't, and hold to it. A team that treats every change as potentially breaking ends up bumping versions so often that integrators stop trusting the version number to mean anything at all.
For example, write the breaking-change rule down as a short list: removing a field, changing a field's type, and changing a required parameter count as breaking, while adding an optional field does not. Publish it beside the versioning scheme so integrators know what to expect from a version number. When a proposed change is ambiguous, default to treating it as breaking. That keeps version bumps meaningful, which is what lets integrators trust that staying on a version is safe until you announce otherwise.
Give integrators a way to see who's still calling the old version
Log every request's API version and, where possible, which API key or account it belongs to. That log is what turns a deprecation from a broadcast announcement into a targeted one: instead of emailing every customer, you can email the specific handful still on the old version and tell them directly.
Sunsetting an API version on a predictable schedule is part of the same discipline that lets a team practice on-demand deployment instead of freezing releases around every breaking change1.
The sunset window that's fair to your slowest integrator
There's no universal right answer here, but the window should be set by how long it realistically takes your slowest integrator to migrate, not by how long your own team wants to keep maintaining two versions. A large enterprise partner with its own release cycle and change approval process needs meaningfully more runway than a small team that can ship a fix the same afternoon.
It also helps to check who's actually still active on the old version partway through the window, not just at the start. A cohort that looked unreachable at the announcement often shrinks on its own as smaller integrators update naturally, leaving a much shorter, more specific list to follow up with directly before the deadline arrives.
What to do with the stragglers on shutdown day
Some accounts will still be calling the old version on the day you'd planned to remove it, no matter how much notice you gave. Decide ahead of time whether shutdown day means an immediate hard cutoff or a final short grace period with a clear, final deadline attached. What doesn't work is quietly extending the deadline every time someone complains, since that just teaches every future integrator that your deadlines aren't real.
For the accounts that genuinely can't move in time, a direct conversation before the deadline, rather than an automated cutoff on the day, tends to preserve the relationship far better than letting them find out their integration is down from their own customers complaining first.
A sunset timeline that avoids surprises can follow these steps:
- Announce the retirement as early as you can, ideally before the replacement version even ships.
- Put the sunset date in the documentation and in a deprecation header on every response from the old version.
- Log the API version and the account behind every request so you can contact the specific integrators still on it.
- Set the window by how long your slowest integrator realistically needs, and check who is still active partway through.
- Decide ahead of time whether shutdown day is a hard cutoff or a final short grace period, and talk directly to accounts that cannot move in time.
What Good Looks Like
Good API deprecation means you can name exactly which accounts are still on the old version at any point before shutdown, not just hope they've moved.
Building The Capability (5-Stage Skill Ladder)
How to Get Started
Frequently Asked Questions
How much notice should we give before retiring an API version?
Enough for your slowest realistic integrator to migrate on their own release schedule, not your preferred one. For a partner with a formal change approval process, that can mean months rather than weeks. Check actual usage logs before assuming everyone has already moved.
Should we ever extend a deprecation deadline?
Sparingly, and only for a specific, identified integrator with a real reason, not as a general policy. Repeatedly moving the deadline for anyone who asks teaches every future integrator that your announced dates are negotiable, which undermines the next deprecation too.
What's the biggest mistake teams make when deprecating an API?
Not tracking who's actually still calling the old version. Without that log, the team is guessing at readiness instead of knowing it, and finds out the hard way on shutdown day when a customer they didn't know about goes down.
Sources
Where we quote a benchmark, we show its source. Other figures in this guide are estimates or general guidance, so check them against your own numbers.
- Deployment frequency by DORA performance cluster (max days between deploys). DORA Accelerate State of DevOps 2024 (Google Cloud), cluster table via Octopus Deploy analysis, 2024.
Related Guides
A Playbook for Deprecating an API Without Breaking Customers
A step-by-step playbook for deprecating an API version: how much notice to give, how to track who's still on it, and when it's safe to shut it off.
Retiring an API Without Breaking Every Integration
A sunset date read as a suggestion breaks three partner integrations at once. A realistic timeline for retiring an API endpoint without the fallout.
How to Sunset an API Version Without Breaking Every Partner
A step-by-step playbook for retiring an old API version: usage auditing, notice periods, migration support, and the hard cutover most teams get wrong.
A Rollout Checklist for Swapping Models in Production
A rollout checklist for swapping AI models in production: evaluation gates, canary and shadow traffic, and fast rollback paths.
How to Version an API Your Model-Serving Clients Depend On
How to design and version an AI model-serving API contract so a model swap never silently breaks a client, including streaming and deprecation windows.
A Playbook for Sunsetting an API Without Breaking Customers
A practical timeline and communication plan for deprecating an API version, including how to find out who's still calling it before shutdown.