name: Deprecation Notices description: Comprehensive guide to API deprecation processes, sunset timelines, communication strategies, and graceful migration paths
Deprecation Notices
What is Deprecation?
Definition: Announcing end-of-life for an API/feature with time for users to migrate before eventual removal.
Lifecycle
Active → Deprecated → Sunset → Removed
Active: Fully supported
Deprecated: Still works, but discouraged (6-12 months)
Sunset: Stops working
Removed: Code deleted
Example
Jan 2024: API v1 active
Jun 2024: API v1 deprecated (announce v2)
Dec 2024: API v1 sunset (stops working)
Jan 2025: API v1 code removed
Why Proper Deprecation Matters
1. Avoid Breaking Users Without Warning
Bad:
Deploy new version
→ Old endpoint removed
→ Users break immediately
→ Angry customers
→ Emergency rollback
Good:
Announce deprecation (6 months notice)
→ Users migrate gradually
→ Sunset date arrives
→ No surprises
2. Maintain Trust
Trust Built By:
- Advance notice (6-12 months)
- Clear migration path
- Support during migration
- No surprises
Trust Broken By:
- Sudden changes
- No warning
- Unclear migration
- Breaking without notice
3. Smooth Migration
Gradual Migration:
Month 0: Announce deprecation
Month 3: 25% migrated
Month 6: 50% migrated
Month 9: 75% migrated
Month 12: 100% migrated, sunset
4. Legal Compliance (If Contractual)
Contracts May Require:
- Minimum notice period (e.g., 12 months)
- Migration support
- No breaking changes without notice
Check Contracts Before Deprecating!
Deprecation Timeline
Typical: 6-12 Months for APIs
Timeline:
Month 0: Announce deprecation
Month 3: Reminder + usage stats
Month 6: Final warning
Month 9: Reach out to remaining users
Month 12: Sunset
Critical Systems: 12-24 Months
Examples:
- Banking APIs
- Healthcare systems
- Government integrations
Why Longer:
- Longer approval processes
- More stakeholders
- Higher risk
Internal APIs: 3-6 Months
Why Shorter:
- Control both sides
- Faster coordination
- Lower risk
Consider: Contract Terms, User Base Size
Factors:
- Contract terms: May require 12+ months
- User base size: More users = longer timeline
- Criticality: Mission-critical = longer timeline
- Complexity: Complex migration = longer timeline
Deprecation Process
Step 1: Mark as Deprecated (Code, Docs)
Code (JavaScript):
/**
* @deprecated Use getUser() instead. Will be removed in v2.0.0.
* @see getUser
*/
function getUserProfile(id) {
console.warn('getUserProfile is deprecated. Use getUser() instead.');
return getUser(id);
}
Code (Python):
import warnings
def get_user_profile(id):
"""
.. deprecated:: 1.5.0
Use :func:`get_user` instead.
"""
warnings.warn(
"get_user_profile is deprecated. Use get_user() instead.",
DeprecationWarning,
stacklevel=2
)
return get_user(id)
Docs:
## GET /users/:id/profile
**⚠️ DEPRECATED:** This endpoint is deprecated and will be removed on December 31, 2024.
**Use instead:** `GET /users/:id`
**Migration guide:** https://docs.example.com/migration/profile-to-user
Step 2: Announce (Email, Blog, Changelog)
Email:
Subject: Deprecation Notice: /users/:id/profile endpoint
Hi developers,
We're deprecating the /users/:id/profile endpoint.
What's changing:
- Endpoint: GET /users/:id/profile
- Sunset date: December 31, 2024
- Replacement: GET /users/:id
Why:
- Consolidating user endpoints for simplicity
- New endpoint provides more data
Action required:
- Update your integration by December 31, 2024
- See migration guide: https://docs.example.com/migration
Need help?
- Reply to this email
- Join office hours: Fridays 2-3pm PT
Thank you,
API Team
Blog Post:
# Deprecation Notice: /users/:id/profile Endpoint
**Date:** June 1, 2024
**Sunset Date:** December 31, 2024
We're deprecating the `/users/:id/profile` endpoint in favor of the consolidated `/users/:id` endpoint.
## What's Changing
The `/users/:id/profile` endpoint will stop working on December 31, 2024.
## Why
We're consolidating user endpoints to simplify our API and provide a better developer experience.
## What to Use Instead
Use `GET /users/:id` instead. It returns the same data plus additional fields.
## Migration Guide
See our [migration guide](https://docs.example.com/migration) for step-by-step instructions.
## Timeline
- **June 1, 2024:** Deprecation announced
- **September 1, 2024:** Reminder email sent
- **December 1, 2024:** Final warning
- **December 31, 2024:** Endpoint stops working
## Need Help?
Contact us at api@example.com or join our office hours.
Changelog:
# Changelog
## v1.5.0 (2024-06-01)
### Deprecated
- **GET /users/:id/profile** - Use GET /users/:id instead. Will be removed on 2024-12-31.
### Added
- **GET /users/:id** - New consolidated user endpoint
Step 3: Monitor Usage
Track Metrics:
app.get('/users/:id/profile', (req, res) => {
// Track usage
metrics.increment('deprecated.users_profile.calls', {
client: req.headers['user-agent'],
clientId: req.user?.clientId
});
// Return response
res.json(profile);
});
Dashboard:
Deprecated Endpoint: /users/:id/profile
Sunset Date: 2024-12-31 (6 months remaining)
Usage:
- Total calls/day: 1,000 (down from 5,000 last month)
- Unique clients: 50 (down from 200)
Top Clients:
1. mobile-app: 500 calls/day
2. web-app: 300 calls/day
3. partner-api: 200 calls/day
Trend: ↓ Declining (good!)
Step 4: Reach Out to Active Users
Email Top Users:
Subject: Action Required: Migrate from /users/:id/profile
Hi [Client],
We noticed you're still using the deprecated /users/:id/profile endpoint (500 calls/day).
This endpoint will stop working on December 31, 2024 (3 months remaining).
Action required:
- Migrate to GET /users/:id
- See migration guide: https://docs.example.com/migration
Need help?
- Reply to this email
- Schedule a call: https://calendly.com/api-team
Thank you,
API Team
Step 5: Sunset (Stop Working)
Return 410 Gone:
app.get('/users/:id/profile', (req, res) => {
res.status(410).json({
error: 'This endpoint has been removed',
message: 'GET /users/:id/profile was removed on 2024-12-31',
replacement: 'Use GET /users/:id instead',
migrationGuide: 'https://docs.example.com/migration'
});
});
Step 6: Remove Code
After Sunset:
1. Sunset date reached (Dec 31, 2024)
2. Monitor for errors (1 month)
3. If no issues, remove code (Jan 31, 2025)
Deprecation Headers (HTTP)
Deprecation: true (Draft RFC)
Header:
HTTP/1.1 200 OK
Deprecation: true
Spec: https://datatracker.ietf.org/doc/html/draft-dalal-deprecation-header
Sunset: Date (RFC 8594)
Header:
HTTP/1.1 200 OK
Sunset: Sat, 31 Dec 2024 23:59:59 GMT
Spec: https://datatracker.ietf.org/doc/html/rfc8594
Link: Migration Guide
Header:
HTTP/1.1 200 OK
Link: <https://docs.example.com/migration>; rel="sunset"
Warning: Message (RFC 7234)
Header:
HTTP/1.1 200 OK
Warning: 299 - "This endpoint is deprecated. Use /v2/users instead. See https://docs.example.com/migration"
All Together
Example:
HTTP/1.1 200 OK
Deprecation: true
Sunset: Sat, 31 Dec 2024 23:59:59 GMT
Link: <https://docs.example.com/migration>; rel="sunset"
Warning: 299 - "This endpoint is deprecated and will be removed on 2024-12-31. Use /v2/users instead."
Content-Type: application/json
{
"id": "123",
"name": "John Doe"
}
Middleware (Express):
function deprecationHeaders(sunsetDate, migrationUrl, message) {
return (req, res, next) => {
res.set('Deprecation', 'true');
res.set('Sunset', sunsetDate);
res.set('Link', `<${migrationUrl}>; rel="sunset"`);
res.set('Warning', `299 - "${message}"`);
next();
};
}
app.get('/users/:id/profile',
deprecationHeaders(
'Sat, 31 Dec 2024 23:59:59 GMT',
'https://docs.example.com/migration',
'This endpoint is deprecated. Use /v2/users instead.'
),
(req, res) => {
res.json(profile);
}
);
OpenAPI Deprecation
deprecated: true
Example:
paths:
/users/{id}/profile:
get:
deprecated: true
summary: Get user profile (DEPRECATED)
description: |
**DEPRECATED:** This endpoint is deprecated and will be removed on 2024-12-31.
**Use instead:** GET /users/{id}
**Migration guide:** https://docs.example.com/migration
responses:
'200':
description: User profile
Swagger UI:
GET /users/{id}/profile (DEPRECATED)
⚠️ Deprecated
This endpoint is deprecated and will be removed on 2024-12-31.
Use GET /users/{id} instead.
GraphQL Deprecation
@deprecated Directive
Example:
type User {
id: ID!
name: String! @deprecated(reason: "Use firstName and lastName instead")
firstName: String!
lastName: String!
}
Query:
{
user(id: "123") {
id
name # Warning: Field 'name' is deprecated. Use firstName and lastName instead.
}
}
Code Deprecation
@deprecated Annotation (Java)
/**
* @deprecated Use getUser() instead. Will be removed in v2.0.0.
*/
@Deprecated
public User getUserProfile(String id) {
return getUser(id);
}
@deprecated JSDoc (JavaScript)
/**
* @deprecated Use getUser() instead. Will be removed in v2.0.0.
* @see getUser
*/
function getUserProfile(id) {
console.warn('getUserProfile is deprecated');
return getUser(id);
}
warnings.warn (Python)
import warnings
def get_user_profile(id):
warnings.warn(
"get_user_profile is deprecated. Use get_user() instead.",
DeprecationWarning,
stacklevel=2
)
return get_user(id)
Communication Channels
In-App Notifications (For Logged-In Users)
Example:
Banner:
⚠️ You're using a deprecated API endpoint (/users/:id/profile).
It will stop working on Dec 31, 2024.
[Migrate Now] [Learn More]
Email Campaigns (To All API Users)
See "Step 2: Announce" above
Blog Post (Public Announcement)
See "Step 2: Announce" above
Changelog (Detailed Info)
See "Step 2: Announce" above
Status Page Updates
Example:
Status: Scheduled Maintenance
API v1 Sunset
Date: December 31, 2024
Impact: API v1 endpoints will stop working
Action: Migrate to API v2
Guide: https://docs.example.com/migration
Release Notes
Example:
# Release Notes - v1.5.0
## Deprecations
- GET /users/:id/profile (sunset: 2024-12-31)
- Use: GET /users/:id
- Guide: https://docs.example.com/migration
Migration Guide
Why Deprecating (Reason)
Example:
## Why We're Deprecating /users/:id/profile
We're consolidating user endpoints to:
1. Simplify our API (fewer endpoints to learn)
2. Improve performance (single endpoint, less overhead)
3. Provide more data (new endpoint returns additional fields)
What to Use Instead (Alternative)
Example:
## What to Use Instead
Use `GET /users/:id` instead of `GET /users/:id/profile`.
The new endpoint returns all profile data plus additional fields.
How to Migrate (Step-by-Step)
Example:
## How to Migrate
### Step 1: Update API Call
**Before:**
```javascript
const profile = await fetch('/api/users/123/profile');
After:
const user = await fetch('/api/users/123');
Step 2: Update Response Handling
Before:
const { bio, avatar, location } = profile;
After:
const { bio, avatar, location } = user;
// Same fields, no changes needed
Step 3: Test
Test your integration in staging before deploying to production.
Step 4: Deploy
Deploy your changes before December 31, 2024.
### Code Examples (Before/After)
See above
### Timeline (When It Stops Working)
**Example:**
```markdown
## Timeline
- **June 1, 2024:** Deprecation announced
- **September 1, 2024:** Reminder email
- **December 1, 2024:** Final warning
- **December 31, 2024:** Endpoint stops working (410 Gone)
Support Contact (If Help Needed)
Example:
## Need Help?
- **Email:** api@example.com
- **Office Hours:** Fridays 2-3pm PT (https://meet.google.com/xxx)
- **Slack:** #api-support
- **Schedule Call:** https://calendly.com/api-team
Monitoring Deprecated Usage
Track API Calls to Deprecated Endpoints
See "Step 3: Monitor Usage" above
Identify Top Users
Query:
SELECT
client_id,
COUNT(*) as call_count
FROM api_logs
WHERE endpoint = '/users/:id/profile'
AND date >= CURRENT_DATE - INTERVAL '7 days'
GROUP BY client_id
ORDER BY call_count DESC
LIMIT 10;
Usage Trends (Is It Declining?)
Chart:
Calls/Day to /users/:id/profile
5000 | ●
4000 | ●
3000 | ●
2000 | ●
1000 | ●
0 |___________●___
Jun Jul Aug Sep Oct Nov
Trend: ↓ Declining (good!)
Alert When Usage Spikes
Alert:
Alert: Deprecated endpoint usage spike
Endpoint: /users/:id/profile
Current: 5,000 calls/day
Previous: 1,000 calls/day
Change: +400%
Action: Investigate (new client using deprecated endpoint?)
Outreach to Users
Email Top Users (Direct Outreach)
See "Step 4: Reach Out to Active Users" above
Offer Migration Support
Email:
Need help migrating?
We offer:
- 1-on-1 migration support calls
- Code review of your migration
- Extended sunset date (if needed)
Schedule a call: https://calendly.com/api-team
Schedule Calls with Major Customers
Process:
1. Identify major customers (high usage)
2. Email to schedule call
3. Call: Explain deprecation, offer help
4. Follow up: Check migration progress
Provide Early Access to New Version
Email:
Early Access: API v2
As a valued customer, we're offering early access to API v2.
Benefits:
- Test v2 before v1 sunset
- Provide feedback
- Smooth migration
Sign up: https://example.com/v2-early-access
Handling Non-Compliant Users
Repeated Notices
Timeline:
Month 0: Initial announcement
Month 3: Reminder email
Month 6: Second reminder
Month 9: Final warning
Month 11: Last chance email
Month 12: Sunset
Escalation (Account Manager)
Process:
1. Email from API team (no response)
2. Email from account manager
3. Phone call from account manager
4. Executive escalation (if major customer)
Final Warning (1 Month Before)
Email:
Subject: URGENT: Action Required - API v1 Sunset in 30 Days
Hi [Client],
This is a final warning that API v1 will stop working in 30 days (December 31, 2024).
We noticed you're still using:
- GET /users/:id/profile (500 calls/day)
Action required:
- Migrate to GET /users/:id immediately
- See migration guide: https://docs.example.com/migration
If you don't migrate, your integration will break on December 31.
Need help? Reply to this email ASAP.
Thank you,
API Team
Hard Cutoff (Stop Working)
Process:
1. Sunset date reached
2. Return 410 Gone
3. Monitor for errors
4. Reach out to affected users
Graceful Degradation
Return 410 Gone (After Sunset)
See "Step 5: Sunset" above
Helpful Error Message (Link to Guide)
Example:
HTTP/1.1 410 Gone
Content-Type: application/json
{
"error": "Endpoint Removed",
"message": "GET /users/:id/profile was removed on 2024-12-31",
"sunsetDate": "2024-12-31",
"replacement": {
"endpoint": "GET /users/:id",
"documentation": "https://docs.example.com/api/users"
},
"migrationGuide": "https://docs.example.com/migration/profile-to-user",
"support": "api@example.com"
}
Optional: Temporary Disable (Test Waters)
Process:
1. Disable endpoint for 1 hour
2. Monitor errors
3. Identify affected users
4. Reach out
5. Re-enable
6. Give more time to migrate
Versioning and Deprecation
v1 Deprecated → Use v2
Timeline:
2024-06: Launch v2
2024-06: Deprecate v1 (12 month notice)
2025-06: Sunset v1
Maintain v1 During Transition
Support:
v2: Active development
v1: Maintenance mode (bug fixes only, no new features)
Eventually Remove v1
Process:
1. Sunset v1 (stop working)
2. Monitor for 1 month
3. Remove v1 code
4. Celebrate! 🎉
Database Schema Deprecation
Multi-Step Migration
See Backward Compatibility Rules skill
Stop Writing to Old Column
Step 1:
-- Stop writing to 'name' column
-- Write to 'full_name' instead
Stop Reading (Use New Column)
Step 2:
-- Stop reading from 'name' column
-- Read from 'full_name' instead
Drop Old Column
Step 3:
-- After all code migrated
ALTER TABLE users DROP COLUMN name;
Feature Flag Deprecation
Mark Feature as Deprecated
Code:
if (featureFlags.isEnabled('old-feature')) {
console.warn('old-feature flag is deprecated. Will be removed in v2.0.0.');
// Old feature code
}
Monitor Usage
Dashboard:
Feature Flag: old-feature
Status: Deprecated
Sunset: 2024-12-31
Usage:
- Enabled for 10 users (down from 100)
- Last enabled: 2024-11-15
Reach Out to Enabled Users
Email:
Subject: Feature Flag Deprecation: old-feature
Hi,
We noticed you have the 'old-feature' flag enabled.
This feature is deprecated and will be removed on 2024-12-31.
Action: Disable 'old-feature' flag and use 'new-feature' instead.
Need help? Reply to this email.
Force Disable
Process:
1. Sunset date reached
2. Force disable flag for all users
3. Monitor for errors
4. Remove feature code
Remove Code
After Sunset:
// Remove old feature code
// Remove feature flag
Real Deprecation Examples
Twitter API v1 → v2
Timeline:
- 2020: v2 launched
- 2021: v1.1 deprecated
- 2023: v1.1 sunset (3 years notice!)
Communication:
- Blog posts
- Email campaigns
- Developer forums
- Migration guides
GitHub API v3 Deprecations
Process:
- Announce deprecation in changelog
- Add deprecation headers
- Provide migration guide
- 12+ months notice
- Sunset
Heroku Free Tier Sunset
Timeline:
- Aug 2022: Announced
- Nov 2022: Sunset (3 months notice)
Controversy:
- Short notice (3 months)
- No free alternative
- Many affected users
Lesson: Give more notice for major changes
Templates
Deprecation Announcement (Email)
See "Step 2: Announce" above
Deprecation Announcement (Blog)
See "Step 2: Announce" above
Migration Guide
See "Migration Guide" section above
API Response Headers
See "Deprecation Headers" section above
Summary
Quick Reference
Deprecation: Announcing end-of-life with time to migrate
Timeline:
- APIs: 6-12 months
- Critical systems: 12-24 months
- Internal APIs: 3-6 months
Process:
- Mark as deprecated (code, docs)
- Announce (email, blog, changelog)
- Monitor usage
- Reach out to active users
- Sunset (stop working)
- Remove code
Headers:
- Deprecation: true
- Sunset: Date
- Link: Migration guide
- Warning: Message
OpenAPI:
deprecated: true
description: Migration guide
GraphQL:
@deprecated(reason: "Use X instead")
Communication:
- In-app notifications
- Email campaigns
- Blog post
- Changelog
- Status page
- Release notes
Migration Guide:
- Why deprecating
- What to use instead
- How to migrate (step-by-step)
- Code examples (before/after)
- Timeline
- Support contact
Monitoring:
- Track usage
- Identify top users
- Usage trends
- Alert on spikes
Outreach:
- Email top users
- Offer migration support
- Schedule calls
- Early access to new version
Non-Compliant:
- Repeated notices
- Escalation
- Final warning
- Hard cutoff
Graceful Degradation:
- 410 Gone
- Helpful error message
- Link to migration guide
Versioning:
- v1 deprecated → v2
- Maintain v1 during transition
- Eventually remove v1
Overview
Deprecation Notices is the practice of announcing end-of-life for an API/feature with time for users to migrate before eventual removal.
Lifecycle
Active → Deprecated → Sunset → Removed
Month 0: Fully supported
Month 3: Deprecated (6-12 months notice)
Month 6: Final warning
Month 12: Sunset (stops working)
Example
Jan 2024: API v1 active
Jun 2024: API v1 deprecated (announce v2)
Dec 2024: API v1 sunset (stops working)
Jan 2025: API v1 code removed
Why Proper Deprecation Matters
1. Avoid Breaking Users Without Warning
Without Deprecation:
Deploy new version
→ All clients break immediately
→ Emergency rollback
→ Coordinate with all clients to update
→ Big bang migration (risky!)
With Deprecation:
Deploy new version
→ Old clients continue working
→ Clients migrate gradually
→ No coordination needed
2. Maintain Trust
Trust Built By:
- Advance notice (6-12 months)
- Clear migration path
- Support during migration
- No surprises
Trust Broken By:
- Sudden changes
- No warning
- Unclear migration
- Breaking without notice
### 3. Smooth Migration
**Gradual Migration:**
Month 0: Deploy v2 (backward compatible) Month 1: 20% of clients migrated Month 3: 50% of clients migrated Month 6: 80% of clients migrated Month 12: 100% migrated, deprecate v1
### 4. Reduce Coordination Overhead
**Without:**
- Coordinate deployment with all clients
- Schedule maintenance window
- Rollback plan if issues
**With:**
- Deploy anytime
- Clients migrate when ready
- No coordination needed
5. Customer Trust (Stable APIs)
Trust:
- "This API won't break my integration"
- "I can upgrade when I'm ready"
- "No surprises"
Deprecation Timeline
Typical: 6-12 Months for APIs
Timeline:
Month 0: Announce deprecation
Month 3: Reminder + usage stats
Month 6: Final warning
Month 12: Sunset
Critical Systems: 12-24 Months
Examples:
- Banking APIs
- Healthcare systems
- Government integrations
Why Longer:
- Longer approval processes
- More stakeholders
- Higher risk
Internal APIs: 3-6 Months
Why Shorter:
- Control both sides
- Faster coordination
- Lower risk
Factors:
- Contract terms: May require 12+ months
- User base size: More users = longer timeline
- Criticality: Mission-critical = longer timeline
- Complexity: Complex migration = longer timeline
Deprecation Process
Step 1: Mark as Deprecated (Code, Docs)
Code (JavaScript):
/**
* @deprecated Use getUser() instead. Will be removed in v2.0.0.
* @see getUser
*/
function getUserProfile(id) {
console.warn('getUserProfile is deprecated. Use getUser() instead.');
return getUser(id);
}
Code (Python):
import warnings
def get_user_profile(id):
"""
.. deprecated:: 1.5.0
Use :func:`get_user` instead.
"""
warnings.warn(
"get_user_profile is deprecated. Use get_user() instead.",
DeprecationWarning,
stacklevel=2
)
return get_user(id)
Docs:
## GET /users/:id/profile
**⚠️ DEPRECATED:** This endpoint is deprecated and will be removed on December 31, 2024.
**Use instead:** `GET /users/:id`
**Migration guide:** https://docs.example.com/migration
Step 2: Announce (Email, Blog, Changelog)
Email:
Subject: Deprecation Notice: /users/:id/profile endpoint
Hi developers,
We're deprecating the `/users/:id/profile` endpoint.
What's changing:
- Endpoint: GET /users/:id/profile
- Sunset date: December 31, 2024
Why:
- Consolidating user endpoints for simplicity
- New endpoint provides more data
Action required:
- Update your integration by December 31, 2024
- See migration guide: https://docs.example.com/migration
Need help?
- Reply to this email
- Schedule a call: https://calendly.com/api-team
Thank you,
API Team
Blog Post:
# Deprecation Notice: /users/:id/profile Endpoint
**Date:** June 1, 2024
**Sunset Date:** December 31, 2024
We're deprecating the `/users/:id/profile` endpoint in favor of the consolidated `/users/:id` endpoint.
What's Changing
The `/users/:id/profile` endpoint will stop working on December 31, 2024.
Why
Consolidating user endpoints to simplify our API and provide a better developer experience.
The new endpoint returns all profile data plus additional fields.
Migration Guide
See our [migration guide](https://docs.example.com/migration) for step-by-step instructions.
Step 3: Monitor Usage
Track Deprecated Endpoint Usage:
app.get('/users/:id/profile', (req, res) => {
// Track usage
metrics.increment('deprecated.users_profile.calls', {
client: req.headers['user-agent'],
clientId: req.user?.clientId
});
// Return response with deprecation headers
res.set('Deprecation', 'true');
res.set('Sunset', 'Sat, 31 Dec 2024 23:59:59 GMT');
res.set('Link', '<https://docs.example.com/migration>; rel="deprecation"');
res.set('Warning', '299 - "This endpoint is deprecated. Use /users/:id instead. See https://docs.example.com/migration"');
res.json(profile);
});
Dashboard:
Deprecated Endpoint: /users/:id/profile
Sunset Date: 2024-12-31 (6 months remaining)
Usage:
- Total calls/day: 1,000 (down from 5,000 last month)
- Top clients: mobile-app (500), web-app (300), partner-api (200)
Deprecation Headers
Sunset Header (RFC 8594):
HTTP/1.1 200 OK
Sunset: Sat, 31 Dec 2024 23:59:59 GMT
Link: <https://docs.example.com/migration>; rel="sunset"
Deprecation Header:
HTTP/1.1 200 OK
Deprecation: true
Link: <https://docs.example.com/migration>; rel="deprecation"
Warning Header:
HTTP/1.1 200 OK
Warning: 299 - "This endpoint is deprecated. Use /v2/users instead. See https://docs.example.com/migration"
Deprecation Policy (6-12 Months Notice)
Timeline:
Month 0: Announce deprecation
Month 3: Reminder + usage stats
Month 6: Final warning
Month 12: Sunset
OpenAPI Deprecation
deprecated: true
paths:
/users/{id}/profile:
get:
deprecated: true
summary: Get user profile (DEPRECATED)
description: |
**DEPRECATED:** This endpoint is deprecated and will be removed on 2024-12-31.
**Use instead:** GET /users/{id}
---
## GraphQL Deprecation
**@deprecated Directive:**
```graphql
type User {
id: ID!
name: String! @deprecated(reason: "Use firstName and lastName instead")
firstName: String!
lastName: String!
}
Code Deprecation
@deprecated Annotation (Java):
/**
* @deprecated Use getUser() instead. Will be removed in v2.0.0.
* @see getUser
*/
@Deprecated
public User getUserProfile(String id) {
return getUser(id);
}
@deprecated JSDoc (JavaScript):
/**
* @deprecated Use getUser() instead. Will be removed in v2.0.0.
* @see getUser
*/
/**
* @deprecated Use getUser() instead. Will be removed in v2.0.0.
*/
function getUserProfile(id) {
console.warn('getUserProfile is deprecated. Use getUser() instead.');
return getUser(id);
}
warnings.warn (Python):
import warnings
def get_user_profile(id):
"""
.. deprecated:: 1.5.0
Use :func:`get_user` instead.
"""
warnings.warn(
"get_user_profile is deprecated. Use get_user() instead.",
DeprecationWarning,
stacklevel=2
)
return get_user(id)
Monitoring Deprecated Usage
Track Metrics:
- Total calls/day
- Unique clients
- Top clients
- Trend (declining = good!)
Reach Out to Active Users
Email Top Users:
Subject: Action Required: Migrate from /users/:id/profile
Hi [Client],
We noticed you're still using the deprecated /users/:id/profile endpoint (500 calls/day).
This endpoint will stop working on December 31, 2024 (3 months remaining).
Action required:
- Migrate to GET /users/:id immediately
- See migration guide: https://docs.example.com/migration
Need help?
- Reply to this email
- Schedule a call: https://calendly.com/api-team
- Schedule a call: https://calendly.com/api-team
Thank you,
API Team
Graceful Degradation
Optional: Temporary Disable
Process:
1. Disable endpoint for 1 hour
2. Monitor errors
3. Identify affected users
4. Reach out
5. Re-enable
6. Give more time to migrate
Helpful Error Message
410 Gone Response:
HTTP/1.1 410 Gone
Content-Type: application/json
{
"error": "This endpoint has been removed. Use /v2/users instead.",
"migrationGuide": "https://docs.example.com/migration",
"support": "api@example.com"
}
Feature Flag Deprecation
Mark Feature as Deprecated
Code:
if (featureFlags.isEnabled('old-feature')) {
console.warn('old-feature flag is deprecated. Will be removed in v2.0.0.');
}
Database Schema Deprecation
Multi-Step Migration
Step 1: Stop Writing to Old Column
-- Stop writing to 'name' column
-- Write to 'full_name' instead
Step 2: Stop Reading (Use New Column)
-- Stop reading from 'name' column
-- Read from 'full_name' instead
Step 3: Drop Old Column
-- After all code migrated
ALTER TABLE users DROP COLUMN name;
Real Deprecation Examples
Stripe API Evolution
Characteristics:
- Excellent consistency
- Comprehensive docs
- Versioning via headers
- Extensive examples
- Idempotency keys
- Webhooks (event-driven)
Learn From:
- Error format (detailed, helpful)
- Pagination (cursor-based)
- Deprecation notices
- Comprehensive SDKs
GitHub API
Characteristics:
- RESTful design
- GraphQL alternative
- Deprecation notices
- Rate limiting
Learn From:
- Deprecation headers
- Preview features (opt-in)
- Comprehensive documentation
Internal API Gateway Patterns
Pattern:
- All APIs go through API gateway → Gateway enforces governance → Rate limiting, auth, logging → Consistent experience
Implementation
Migration Guide
Example:
## How to Migrate
### What's Changing
The `/users/:id/profile` endpoint is deprecated. Use `/users/:id` instead.
### Why
We're consolidating user endpoints to simplify our API and provide a better developer experience.
### How to Migrate
### Before
```javascript
const profile = await fetch('/api/users/123/profile');
After
const user = await fetch('/api/users/123');
Timeline
- June 1, 2024: Deprecation announced
- September 1, 2024: Reminder email
- December 1, 2024: Final warning
- December 31, 2024: Endpoint stops working (410 Gone)
---
## Templates
### Deprecation Announcement (Email)
See "Step 2: Announce" section above
### Deprecation Announcement (Blog)
See "Step 2: Announce" section above
---
## Best Practices
### Communication
- [ ] Communicate changes early
- [ ] Provide migration guides
- [ ] Hold breaking change meetings
- [ ] Create data contracts with consumers
- [ ] Document breaking changes clearly
- [ ] Document breaking changes with dates
- [ ] Set appropriate notice period (6-12 months minimum)
- [ ] Monitor deprecated endpoint usage
- [ ] Track consumer adoption
- [ ] Reach out to active users
- [ ] Provide support during migration
- [ ] Send reminders at key milestones
- [ ]
### Documentation
- [ ] Document all breaking changes with dates
- [ ] Document breaking changes clearly
- [ ] Provide migration guides for consumers
- [ ] Document version compatibility
- [ ] Document migration timeline
- [ ] Document sunset dates
- [ ] Keep documentation in sync with code
- [ ] Use consistent deprecation headers
- [ ] Use appropriate deprecation headers
- [ ] Include migration guide links
- [ ] Document breaking changes in changelog
- [ ] Document examples in documentation
- [ ] Document breaking changes in API docs
- [ ] Document breaking changes in README
- [ ] Document breaking changes in Swagger UI
- [ ] Document breaking changes in ReDoc
- [ ]
### Migration
- [ ] Use zero-downtime migration pattern
- [ ] Use multi-step migrations for breaking changes
- [ ] Backfill data before removing old columns
- [ ] Test migrations in staging environment
- [ ] Provide rollback procedures
- [ ] Monitor migration progress
- [ ] Support consumers during migration
- [ ] Use feature flags for gradual rollout
- [ ] Maintain backward compatibility during migration
- [ ] Use canary deployments for testing
- [ ]
### Monitoring
- [ ] Track deprecated endpoint usage
- [ ] Monitor breaking change impacts
- [ ] Track consumer adoption of new schema
- [ ] Set up dashboards for API health
- [ ] Alert on high usage of deprecated endpoints
- [ ] Monitor migration success rates
- [ ] Track time to sunset
- [ ]
### Testing
- [ ] Test backward compatibility
- [ ] Test with production-like data
- [ ] Test migration scripts thoroughly
- [ ] Test graceful degradation scenarios
- [ ] Monitor test coverage
- [ ]
### Prevention
- [ ] Use data contracts for all shared data
- [ ] Enforce schema validation at source
- [ ] [ ] Implement CI/CD schema checks
- [ ]
### Version Control
- [ ] Use semantic versioning
- [ ] Tag all releases with version numbers
- [ ] Document version compatibility matrix
- [ ] Maintain backward compatibility
- [ ] Use @deprecated directive for breaking changes
- [ ]
### Legal Compliance
- [ ] Follow contract terms if applicable
- [ ] Provide minimum notice period
- [ ] Ensure migration support
- [ ] Document breaking changes clearly
- [ ] Provide migration guides
- [ ] Maintain deprecation records
### Checklist
- [ ] Define deprecation process
- [ ] Set appropriate notice period
- [ ] Document breaking changes clearly
- [ ] Provide migration guides
- [ ] Monitor deprecated endpoint usage
- [ ] Track consumer adoption
- [ ] Set up dashboards for API health
- [ ] Track migration success rates
- [ ] Test backward compatibility
- [ ] Test with production-like data
- [ ] Monitor test coverage
- [ ] Optimize deprecation headers
- [ ] Use feature flags for gradual rollout
- [ ] Use zero-downtime migrations
- [ ] Backfill data before removing old columns
- [ ] Test migrations in staging environment
- [ ] Have rollback procedures ready
- [ ] Monitor schema drift metrics
- [ ] Track breaking change impacts
- [ ] Track consumer adoption of new schema
- [ ] Set up change notifications
- [ ] Test with production-like data
- [ ] Monitor test coverage
- [ ] Optimize schema validation overhead
- [ ] Cache schema definitions
- [ ] Use efficient validation libraries
- [ ] Monitor schema performance impact
- [ ] Establish schema ownership
- [ ] Create schema review process
- [ ] Define schema lifecycle
- [ ] Plan schema deprecation strategy
- [ ] Set up incident response for violations
- [ ] Test schema validation logic
- [ ] Train team on deprecation best practices