How should I run the sunset process when deprecating an endpoint in my public API?
Question
I run a public API and I've flagged three legacy endpoints for removal. But several paying partners still hit those endpoints every single day. How do I retire these endpoints without breaking the partners' integrations? How should I run the sunset process step by step, what signals should I send, and when exactly should I actually cut it off?
Answer
Short answer: never silently delete an endpoint paying partners use. Run an announced, dated, measured sunset — communicate, signal it in the response, watch usage drop to zero, then remove it.
The core mistake is treating removal as an engineering event when it’s really a communication process; the code change that finally deletes the route is the last and smallest step of the whole thing.
- Announce with a hard date and a migration path. Email + changelog + docs; give the partner a concrete replacement and a realistic window (weeks/months for paying B2B, not days). No date means no urgency, and no urgency means nobody migrates.
- Signal it in the response itself. Add the RFC 8594
Sunsetheader + aDeprecationheader + aLinkheader to the migration docs on every response from the doomed endpoint. That way machines and logs see it too, not just humans who ignore the email. - Measure usage per consumer. You can’t retire what you can’t see. Log calls by API key/partner; you need to know exactly who still calls it and how often, and reach those partners directly.
- Run brownouts before you cut. As the date approaches, apply short, scheduled outages (return
410/503for a few minutes, escalating the duration). This surfaces integrations that ignored every header and email while the impact is still reversible. - Return the right status on removal. Not a silent
500; return410 Gone(or404) with a body that explains the replacement. Keep that explanatory response up for a long time after removal. - Keep an escalation valve. For a big paying partner mid-migration, a temporary allowlist/extension beats breaking their production. Contractual/SLA reality outranks a tidy deprecation calendar. Just document who got an extension and until when, so the valve doesn’t quietly become permanent.
HTTP/1.1 200 OK
Deprecation: true
Sunset: Sat, 31 Oct 2026 23:59:59 GMT
Link: <https://api.example.com/docs/migrate-v2>; rel="deprecation"; type="text/html"
Bottom line: personally I’d instrument per-partner usage first, then publish a dated sunset with those headers on every response, run a couple of brownouts near the date, and only cut when usage is near zero — while leaving a manual extension valve for the one partner who always misses the memo. In a public API, reputation is lost with a single silent removal.
Related Reading
Comments
Sign in with your GitHub account to join the discussion. Comments are stored in GitHub Discussions.