deprecation-notices
Comprehensive guide to API deprecation processes, sunset timelines, communication strategies, and graceful migration paths
Installation
Follow the repository instructions for this skill and your agent. Review the files and dependencies before adding it to your workflow.
View source ↗GuidesSkill instructions
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
Examples
Read the usage examples in the source repository.
View source ↗Source history
- Indexed on
- 2026-01-20
- Index updated
- 2026-01-26
- Branch
- main
Index and sync dates describe this directory. View the source repository for code history.
GitHub ↗chat Comments (0)
Sign in to join the discussion and leave a comment.
No comments yet. Be the first to share your thoughts!