Home / Blog / API deprecation without burning your consumers: a 6-month playbook

API deprecation without burning your consumers: a 6-month playbook

Moving an API from v1 to v2 is more than a URL change. Here is how to shape a six-month deprecation cycle: consumer communication, breaking-change management, and the cutover.

When you deprecate a public API, or an internal-but-stable one, missing a proper timeline turns the rollout into chaos. Consumers get surprised, support tickets pile up, and you end up rolling back at the last minute.

Over the last two years I’ve run three deprecation cycles. What worked, what didn’t, and the ideal shape of a six-month process.

Why deprecation is hard

“We launched v2, everyone switch over” doesn’t work. Consumers have to:

  • Carve out engineering bandwidth for the migration
  • Validate in a test environment
  • Roll out gradually to production
  • Accept downtime risk
  • Juggle it against their other priorities

You can’t just kill an API with active v1 traffic. Consumers break and trust goes with them.

The deprecation cycle has to be structured.

The six-month timeline

This timeline comes from my three deprecation cycles:

T-180 days (announcement): v2 launches, v1 deprecation announced. Migration guide ready. Consumers informed.

T-120 days: a deprecation warning lands in response headers. The analytics dashboard shows v1 usage per consumer.

T-90 days: outreach to major consumers. Migration assistance on offer. Progress tracking active.

T-60 days: daily rate limit on v1 starts dropping (warning stage). Email blast.

T-30 days: v1 responses carry a Sunset header. 410 Gone is on the calendar.

T-0 (sunset): v1 returns 410 Gone. The endpoint is closed.

T+30: v1 URL route is removed entirely (now 404).

T-180: announcement

Announce at the same moment across these channels:

  1. API changelog page: website, RSS feed, automatic notification to subscribers
  2. Email: to registered developers and consumers
  3. Developer dashboard: a banner on login
  4. Blog post: details, migration path, FAQ
  5. Status page: an entry under upcoming deprecations

Contents of the announcement:

v1 deprecation schedule:
- Date: 2026-10-15 sunset (180 days)
- v2 available now: https://api.example.com/v2/
- Migration guide: https://docs.example.com/migrate-v1-to-v2
- What's new: [feature list]
- Breaking changes: [list with examples]
- Support: developer-support@example.com

Clear deadline, clear migration path, clear help channel.

T-120: warning header

Every v1 response now carries:

Deprecation: true
Sunset: Thu, 15 Oct 2026 00:00:00 GMT
Link: <https://docs.example.com/migrate-v1-to-v2>; rel="deprecation"

RFC 8594 (Sunset header) is the standard. Modern API clients log this header and notify the dev team automatically.

Usage tracking

The most important data during a deprecation cycle: which consumer is still hitting v1?

Query the analytics log:

SELECT 
    api_key,
    consumer_name,
    COUNT(*) as request_count,
    MAX(request_timestamp) as last_request
FROM api_log
WHERE endpoint LIKE '/v1/%'
  AND request_timestamp > NOW() - INTERVAL '7 days'
GROUP BY api_key, consumer_name
ORDER BY request_count DESC;

Track the top 20 consumers by hand. Offer each of them migration support.

Dashboard view: how is weekly v1 request count trending? A line going down and to the right is the healthy shape.

T-90: proactive outreach

1-on-1 communication with high-volume consumers:

  • Email: “your v1 usage is high, would you like some help?”
  • Slack/Discord: a technical Q&A channel
  • Video call: for the complex integrations

I did one Zoom with each high-volume consumer across three deprecations. Practical questions like “how do we move this endpoint?” get answered on the spot.

Migration speed roughly doubled.

Breaking change catalog

The heart of the migration guide: before and after for every breaking change.

### Change 1: `/v1/users/{id}` response format

Before:

json
{
“id”: 123,
“name”: “Ali”,
“email”: “ali@example.com”
}


After:

json
{
“id”: “u_abc123”, // String ID now
“profile”: {
“name”: “Ali”,
“email”: “ali@example.com”
}
}


**Migration**: 
- ID type change: integer to string
- Profile fields are now nested
- Code change example: [migration snippet]

Before, after, and migration for every breaking change. The consumer can copy-paste into their own code.

T-60: rate limit reduction

With 60 days left, if v1 usage is still there, drop the rate limit. It’s an aggressive signal:

  • Normal: 1000 req/min
  • T-60: 500 req/min
  • T-30: 100 req/min

The consumer notices, hits the limit, and migration bandwidth jumps up the priority list.

This pattern needs care so critical consumers don’t take a hit. Give major clients advance notice and accept waiver requests.

T-30: sunset header plus a last reminder

The final 30 days:

  • Sunset: 2026-10-15 00:00:00 GMT header on every response
  • Final reminder email
  • Countdown on the consumer dashboard
  • “410 Gone after this date” message

By this point every consumer should have committed to migrate or freeze.

T-0: cutover day

Cutover can be gradual behind a feature flag:

  1. 00:00 UTC: return 410 Gone for 10% of v1 traffic
  2. 06:00 UTC: 50% at 410
  3. 12:00 UTC: 100% at 410

Batches, not a hard cut. Panicked consumers still get to call support while the damage is limited.

The 410 Gone response:

{
    "type": "/errors/api-version-sunset",
    "title": "API Version Sunset",
    "status": 410,
    "detail": "API v1 was sunset on 2026-10-15. Please migrate to v2.",
    "migration_url": "https://docs.example.com/migrate-v1-to-v2"
}

Migration link in the error body. It routes panic away from your support desk and toward the fix.

T+30: route cleanup

Thirty days later you can delete the v1 route from the codebase. Traffic is gone (the ones that got 410 have accepted it; the ones that would now get 404 have already migrated).

Clean routing table, smaller codebase, less mental overhead for the team.

Tone of consumer communication

Tone matters during deprecation. Partner, not enemy:

  • Not “v1 is no longer supported” but “v2 is better, we’re here to help you migrate”
  • Hard deadline with flexibility (a 30-day extension for a critical consumer)
  • No blaming (“why haven’t you migrated yet?” becomes “is there anything you’re stuck on?”)

A deprecation tests consumer trust. Handle it badly and they’ll push back on the next change.

Exceptional extensions

Some consumers have legitimate reasons:

  • “We’re in a Q4 freeze, migration in Q1”
  • “Critical integration, testing takes weeks”
  • “We’re in an acquisition, no engineering capacity”

In these cases I grant an extension. Usually 30 to 60 extra days. But I get a commitment: “definitely migrating in 30 days” plus a progress check-in.

No ad-hoc extensions: documented reason, documented commitment.

Internal API deprecation

For internal APIs the cycle can be shorter (3 to 6 weeks). Consumers are in the same company, communication is direct, iteration is fast.

Same pattern though:
– Announcement
– Warning header
– Usage tracking
– Outreach to high-volume consumers
– Cutover

Even three weeks needs discipline, otherwise the migration is chaotic.

Post-mortem

After the cycle, run a team retro:

  • Was the timeline too long or too short?
  • Which consumers had problems?
  • Which migration step was unclear?
  • What do we change for the next deprecation?

That retro document feeds directly into the next deprecation.

Final take

API deprecation isn’t a kill-and-walk-away process; it’s a partnership with your consumers. Six months plus clean communication plus migration help.

Short cycles (1 to 2 months) produce angry customers. Long cycles (12+ months) produce engineering debt.

Six months is the sweet spot. A disciplined timeline and transparent communication keep the deprecation healthy.

Have a project on this topic?

Leave a brief summary — I’ll get back to you within 24 hours.

Get in touch