Your Customers Are Still on v1 Because Nobody Wrote the Migration Guide
You shipped v2 of your API eighteen months ago. It's faster, the resource model makes more sense, and it fixes design mistakes everyone on the team regrets. You announced a deprecation date for v1. Then the date came close, someone pulled the traffic numbers, and a big share of your paying customers were still on v1. Some of them were your largest accounts. The date slipped, and now you're running two APIs, patching security issues in both, and explaining to leadership why the old one can't be turned off.
The usual explanation is that customers are slow or don't care. Usually it's something else. Nobody told them what the migration would actually involve. A developer can't put "move to v2" on a sprint board until they know how big the job is. If your docs don't tell them, the job never gets scheduled.
A deprecation notice is not a migration plan
Most API teams treat a version change as a communication problem. They send the email, post the changelog entry, put a banner on the old reference pages, and assume the job is done. Each of those says that something is changing. None of them says what the customer has to do about it.
Look at it from the other side. A developer at a customer company gets your deprecation email. Before they can do anything, they have to answer questions their manager will ask:
- Which parts of our integration touch the endpoints that are changing?
- Is this a find-and-replace, or do we have to rethink how we store data?
- Can we migrate one piece at a time, or does everything have to switch at once?
- How do we test it before we cut over?
- What happens on the date if we haven't finished?
If the developer has to work all of that out by comparing two API references side by side, the migration becomes a research project before it's an engineering project. Research projects with no deadline pressure lose to feature work every time. So the customer waits until the deadline is close enough to hurt, then files an urgent ticket, or asks for an extension, or starts looking at your competitors.
What a real migration guide contains
A migration guide is a separate document from the changelog and from the v2 reference. It's written for someone who knows v1 well and needs to get to v2 without breaking production. Here's what mine always include:
- A one-paragraph summary of why the change happened. Developers accept extra work more readily when they understand the reason, and it helps them predict the rest of the design.
- An effort estimate by integration type. "If you only read orders, expect a few hours. If you create orders with custom line items, plan for a few days." This is what lets someone schedule the work.
- A complete change inventory. Every removed endpoint, renamed field, changed type, new required parameter, and changed default, each one marked as breaking or not. If you leave something out, it shows up later as a production incident.
- Old-to-new mappings with code. Show the v1 call and the equivalent v2 call next to each other. Wherever behavior changed, not just names, say so in plain language.
- A coexistence strategy. Can a client use v1 and v2 at the same time with the same credentials? Do IDs carry over? Can webhooks be moved separately? This decides whether the migration can be incremental, and incremental migrations actually get done.
- A testing path. Where to try v2 safely, and how to check that the results match what v1 returned.
- The timeline and what happens at each date. Not just the shutdown date. What changes at deprecation, and whether requests fail hard at sunset or degrade first.
Item 4 is where most guides are thin. A bare list of renamed fields isn't enough. A mapping like this tells the developer what to change and what behavior to watch for:
v1: GET /v1/customers?page=3&per_page=50
v2: GET /v2/customers?limit=50&starting_after=cus_123
Behavior change: v2 uses cursor pagination. Page numbers no longer
exist. If you store page offsets to resume a sync, store the last
customer ID you processed instead.
The last line is the important one. It's the change that would quietly break a nightly sync job, and a field-by-field diff would never show it.
Let the API tell clients, too
Email gets filtered and banners get ignored. The one channel you know a developer's code reads is your HTTP responses. Two IETF specifications cover this. RFC 9745 defines a Deprecation response header that says when a resource was or will be deprecated, plus a deprecation link relation that points to human-readable documentation. RFC 8594 defines a Sunset header for the date a resource is expected to stop responding.
Deprecation: @1767225599
Sunset: Wed, 30 Jun 2027 23:59:59 GMT
Link: <https://developer.example.com/migrate/v1-to-v2>; rel="deprecation"; type="text/html"
The Deprecation value is a Unix timestamp in Structured Fields date format (this one is the end of 2025), and the Sunset date must not be earlier than it. RFC 9745 is explicit that deprecation doesn't change how the resource behaves; the headers are hints. That's the point. Nothing breaks, but any client that logs response headers, and any API gateway or monitoring tool that watches for them, now has a machine-readable warning and a link straight to your migration guide. Point that link at the guide, not the changelog.
Find out who is actually stuck
You don't have to guess which customers will struggle. Before you write a word, pull v1 traffic grouped by API key and endpoint. That tells you which endpoints still carry real volume, which customers use them, and which deprecated features they depend on. Write the guide for the integrations you actually have, in order of traffic, rather than for the full surface of v1.
Then read the support tickets from customers who already migrated. Every "how do I do X in v2?" ticket is a gap in the guide, and the customers who haven't migrated yet will hit the same gaps.
Why the v2 team shouldn't write this alone
The engineers who designed v2 are the right people to review a migration guide and usually the wrong people to write it alone. They've lived with the new model for a year. Cursor pagination feels obvious to them, so they don't think to warn anyone about stored page offsets. A good migration guide comes from someone who can read both versions' code and specs, works through the migration the way a customer would, and writes down every point where it gets confusing. That's the same discipline behind keeping docs in sync with the code, which I wrote about in Your API Documentation Is Drifting, and Your Support Queue Knows It.
If you have an old API version you can't turn off because customers won't move, I can help. I'll review your v1 traffic and existing docs, handle the migration myself, and write the guide your customers need to schedule it. Get in touch and tell me where things stand.