Add API Deprecation Headers
Announce deprecation with Deprecation, Sunset, and Link headers, keep clients informed, and remove the old endpoint only after the sunset date.
Task
Deprecate an API endpoint without breaking clients that have not migrated yet.
When to use this
An endpoint is being replaced. Clients keep calling it with no warning, and the team is unsure when it is safe to remove.
Prerequisites
- An API gateway or application that can set response headers
- A documented replacement endpoint
- A migration and analytics plan for client usage
Steps
1. Set the Deprecation header, a Sunset date, and a Link to the replacement on every response from the old endpoint.
app.use('/api/v1/legacy', (req, res, next) => {
res.setHeader('Deprecation', 'true');
res.setHeader('Sunset', 'Wed, 31 Dec 2026 23:59:59 GMT');
res.setHeader('Link', '</api/v2/resource>; rel="successor-version"');
next();
});
Expected output: Every legacy response carries the three headers.
2. Log calls with the client id and endpoint, and build a migration dashboard before the removal date.
logger.warn({
event: 'deprecated_endpoint',
clientId: req.clientId,
route: req.originalUrl,
}, 'legacy endpoint used');
Expected output: The dashboard shows which clients still depend on the old endpoint.
3. Remove the endpoint only after the sunset date and after confirming that the remaining usage is acceptable, with a documented exception process.
curl -sI https://api.example.com/api/v1/legacy | grep -iE 'deprecation|sunset|link'Expected output: The headers are visible until the endpoint is retired.
Troubleshooting
Problem
Clients ignore the warning
Solution
Contact high-volume clients directly and add a migration guide; headers alone are easy to miss.
Problem
The sunset date passes with active clients
Solution
Decide whether to extend with a new date or break the contract; do not silently leave the endpoint running forever.
Limitations
- Header support varies across clients; pair the headers with documentation and direct communication.
- Deprecation is a contract change; it needs an owner and a reviewed date.
Make the warning visible
Deprecation headers put the migration deadline in the response itself. Deprecation signals that the endpoint is deprecated, Sunset gives the removal date, and Link points to the replacement. Clients that log headers can surface the warning long before the removal.
Deprecation: true
Sunset: Wed, 31 Dec 2026 23:59:59 GMT
Link: </api/v2/resource>; rel="successor-version"
Measure real usage
Headers do not prove that clients migrated. Log calls by client and endpoint, and build a dashboard that shows active callers over time. Contact the top consumers directly. If usage does not reach zero, either extend the date with a new sunset or accept a documented breaking change.
Remove with evidence
Retire the endpoint after the sunset date only when the remaining callers are known and handled. Remove the headers, the route, and any compatibility branches, and update the docs. A deprecated endpoint left running indefinitely is technical debt and a security surface.
Verify the response
Expected outcome: every response from the legacy route includes Deprecation, Sunset, and a Link to the successor, and the migration dashboard records the client id and route. Confirm with curl -sI against the deployed route and by checking that a call appears in the usage log. After retirement, the same request should return 404 or 410, not an unmarked successful response.