Definition
The Sunset HTTP Header (RFC 8594) is a standard header that communicates when an API endpoint, resource, or service will be permanently retired. It provides a machine-readable timestamp allowing clients to programmatically detect and handle deprecations.
The header format is:
Sunset: <HTTP-date>
Where <HTTP-date> is an RFC 7231 formatted date (e.g., Sat, 31 Dec 2024 23:59:59 GMT).
The Sunset header is typically used in combination with:
Deprecation: true- Indicates the resource is deprecatedLink: <url>; rel="deprecation"- Points to migration documentationLink: <url>; rel="successor-version"- Points to replacement endpoint
Example
Twilio API Sunset Notification:
Twilio uses Sunset headers to communicate API version retirement:
GET /2010-04-01/Accounts/AC123/Messages.json HTTP/1.1
Host: api.twilio.com
Authorization: Basic <credentials>
HTTP/1.1 200 OK
Deprecation: true
Sunset: Sun, 01 Jun 2025 00:00:00 GMT
Link: <https://www.twilio.com/docs/api/2024-01-01>; rel="successor-version"
Link: <https://www.twilio.com/docs/api/migration/2010-to-2024>; rel="deprecation"
Warning: 299 - "This API version will be sunset on 2025-06-01"
{
"messages": [
{"sid": "SM123", "body": "Hello"}
]
}
Client response:
- Parser detects
Sunsetheader - Compares date to current time
- Logs warning if sunset is within 90 days
- Alerts development team to plan migration
Code Example
# Server response with Sunset header
HTTP/1.1 200 OK
Date: Thu, 09 Jan 2026 10:00:00 GMT
Sunset: Wed, 31 Dec 2026 23:59:59 GMT
Deprecation: true
Link: <https://api.example.com/v2/users>; rel="successor-version"
Link: <https://docs.example.com/migration/v1-v2>; rel="deprecation"
Content-Type: application/json
{
"users": [{"id": 1, "name": "Alice"}]
}
Client-side Sunset detection (JavaScript):
class SunsetDetector {
async fetch(url, options = {}) {
const response = await fetch(url, options);
const sunsetHeader = response.headers.get('Sunset');
if (sunsetHeader) {
const sunsetDate = new Date(sunsetHeader);
const now = new Date();
const daysUntilSunset = Math.floor((sunsetDate - now) / (1000 * 60 * 60 * 24));
// Critical: Less than 90 days
if (daysUntilSunset < 90) {
console.error(`🚨 API sunset in ${daysUntilSunset} days: ${url}`);
// Extract migration guide
const linkHeader = response.headers.get('Link');
const migrationGuide = linkHeader
?.match(/<([^>]+)>; rel="deprecation"/)?.[1];
console.error(`Migration guide: ${migrationGuide}`);
// Report to monitoring
this.reportSunsetAlert({
url,
sunsetDate: sunsetDate.toISOString(),
daysRemaining: daysUntilSunset,
migrationGuide
});
}
// Warning: 90-180 days
else if (daysUntilSunset < 180) {
console.warn(`⚠️ API sunset in ${daysUntilSunset} days: ${url}`);
}
}
return response;
}
reportSunsetAlert(data) {
// Send to logging/monitoring system
fetch('https://monitoring.example.com/api/alerts', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
type: 'API_SUNSET_WARNING',
severity: data.daysRemaining < 90 ? 'critical' : 'warning',
...data
})
});
}
}
// Usage
const detector = new SunsetDetector();
const response = await detector.fetch('https://api.example.com/v1/users');
Diagram
sequenceDiagram
participant Client
participant API Gateway
participant Backend
participant Monitoring
Note over API Gateway: v1 deprecated
Sunset: 2026-12-31
Client->>API Gateway: GET /v1/users
API Gateway->>Backend: Forward request
Backend->>API Gateway: 200 OK + data
API Gateway->>Client: 200 OK
Sunset: Wed, 31 Dec 2026 23:59:59 GMT
Deprecation: true
Client->>Client: Parse Sunset header
Client->>Client: Calculate days until sunset
alt Days < 90
Client->>Monitoring: CRITICAL: API sunset imminent
Monitoring->>Client: Create incident ticket
else Days 90-180
Client->>Monitoring: WARNING: Plan migration
end
Client->>Client: Extract Link header
Client->>API Gateway: GET /docs/migration/v1-v2
API Gateway->>Client: Migration guide
Best Practices
1. Always Include Sunset with Deprecation
If you set Deprecation: true, also set a Sunset header with a specific date. Never deprecate without a sunset timeline.
2. Give Adequate Notice Set sunset dates at least 12-18 months in the future for public APIs, 6-12 months for internal APIs.
3. Use RFC 7231 Date Format
Always use HTTP-date format: Sun, 06 Nov 1994 08:49:37 GMT. This is the standard format parsable by all HTTP clients.
4. Combine with Link Headers
Provide rel="successor-version" pointing to the replacement endpoint and rel="deprecation" pointing to migration documentation.
5. Monitor Client Behavior Track which clients still call endpoints with Sunset headers. Alert teams directly if they haven’t migrated.
6. Don’t Move Sunset Dates Backward You can extend a sunset date (move it forward) if needed, but never shorten the timeline. This breaks trust.
7. Return 410 Gone After Sunset
Once the sunset date passes, return 410 Gone instead of 200 OK. Optionally include a redirect to the new endpoint.
8. Automate Detection Build tooling that scans API responses for Sunset headers and creates alerts in CI/CD pipelines or monitoring dashboards.
Common Mistakes
1. Using Non-Standard Date Formats
Using ISO 8601 (2026-12-31T23:59:59Z) instead of RFC 7231 format breaks parsers expecting HTTP-date.
2. Sunset Without Deprecation
Setting a Sunset header without Deprecation: true is confusing. Always set both.
3. No Migration Guide Including a Sunset header without a Link to migration documentation leaves clients guessing what to do.
4. Sunset Date Too Soon Setting a sunset date only 3-6 months out doesn’t give enterprise clients enough time to plan and deploy migrations.
5. Ignoring the Sunset Date Failing to actually retire the endpoint after the sunset date undermines trust. Clients may ignore future deprecation warnings.
6. Changing Sunset Dates Frequently Moving sunset dates multiple times creates confusion. Set realistic timelines from the start.
7. Not Enforcing After Sunset Allowing deprecated endpoints to continue working indefinitely after sunset prevents cleanup and technical debt reduction.