What is the HTTP `Sunset` header?
Deprecating API endpoints has always been painful because there's no 'one true way' to do it, which makes communicating deprecations to API consumers hard. Ideally we'd sidestep the issue by only ever evolving our API with backwards-compatible changes, but despite our best efforts that's not always possible.
How do you deprecate a REST endpoint, or a field on a resource?
- Mark it
deprecated
in your OpenAPI document? - Maybe your API responses have a
meta
property you can stash a warning inside? - Send an email to your API consumers informing them about the upcoming deprecation?
- Update your documentation to refer to the new, preferred endpoint and hope everyone moves over eventually?
- Bite the bullet and maintain migrations for old API requests, like Stripe does?
Most likely you'll do some combination of those actions, and then hope that your consumers take heed. If you're lucky enough to be dropping an endpoint it's fairly easy to verify when it's no longer in use, but field-level deprecations are hard.
GraphQL requiring consumers to specify the properties they want upfront greatly streamlines field deprecations. Tools like Apollo Studio can analyze queries and tell you precisely when a field is no longer in use–but that's not so with REST. If you want to be really safe then the only way to detect this would be to ask consumers to send an additional parameter indicating they're ready for the field to be deleted.
There's a better way
I ran across a cool Ruby gem the other day called faraday-sunset
. It's a middleware for the Faraday HTTP client which looks for a Sunset
header in responses, and logs a deprecation warning when one is found.
Sunset
is a draft HTTP header which standardizes API deprecations. When a consumer requests a deprecated resource, the API server can send back a Sunset
header with a date value representing the time the endpoint will be removed. The draft also allows for linking to page which explains the deprecation via the already standard Link
header.
A standard method for deprecating APIs is really useful. If there's a golden path then automated tools can be built around it to streamline developer experience–which is exactly what's happened with the faraday-sunset
Ruby gem.
It's easy to imagine a world where your API client has a middleware that logs a message whenever a Sunset
header is encountered. You can be smart about the logging, too: a sunset date far into the future might only be worth a warning-level log whereas a sunset date that's imminent is urgent and deserving of an error log.
High performing DevOps teams ritually checking their system logs can then get early warning about upcoming API deprecations in a consistent manner–regardless of the vendor.
The web keeps getting better
The web is complicated, and there are a lot of articles written by engineers burnt out from constant change in the web ecosystem. But the Sunset
header is a great example of a small adjustment to web standards which actually winds up reducing complexity.
While you should still fire out deprecation warnings to your usual channels–especially so while the header is still in draft!–the Sunset
header is far more robust than sending an email to a shared developers@
inbox that no one's closely monitoring. It's hard to build robust alerting and monitoring systems on top of email, and really easy to monitor and alert on HTTP headers.
Try using Sunset
in your own applications. On the server you don't really need anything as it works just like any other header, and if you're working with Javascript there's a nice package called sunset-header-interceptor
which works just like the faraday-sunset
gem.
Got a GraphQL service?
I wrote a library called graphql-sunset
which makes it easy to use the Sunset
header to communicate breaking changes in your GraphQL service. Read more about the library here.