Where migration time actually goes
Reading the release notes is the cheap part. In practice the expensive parts of an API migration are, roughly in order: working out whether a change affects this codebase at all, finding every call site that touches the changed behavior, writing and reviewing the patch, and then building enough confidence that nothing else changed to merge it.
Each of those steps has a provider-side lever. The rest of this guide goes through them in the order a customer hits them.
Publish precise, machine-readable changelogs
A changelog entry that says "improved invoice handling" forces every customer to go and find out what that means. A useful entry names the exact operation, field or behavior that changed, says whether it is breaking, states which version it lands in and links to the migration path.
Publish the same information in a structured form alongside the prose. It does not need a standard; it needs to be consistent and stable:
- id: 2026-09-01-invoice-amount-units
version: "2026-09-01"
breaking: true
operations: ["GET /invoices", "GET /invoices/{id}"]
change: "amount is now an integer in minor units (was decimal major units)"
migration: "multiply by 100 on read, or read amount_decimal during the transition"
sunset_of_previous: "2027-03-01"A structured feed lets customers filter for changes that touch the operations they actually call, and lets tooling (including their own scripts) do that automatically. Pair it with Deprecation and Sunset headers on the affected responses so the signal also reaches teams that never read changelogs. The API deprecation guide covers the header details.
Ship the OpenAPI diff, not just the new spec
If you publish an OpenAPI document, publish the diff between versions too. Customers can generate it themselves, but most will not, and the ones who do will each make slightly different choices about what counts as breaking. Running the OpenAPI diff in your own release pipeline and attaching the result to the release means everyone works from the same list.
The diff also keeps you honest. If the spec diff for a release you described as non-breaking shows a removed enum value or a newly required parameter, you want to know before your customers do. Be explicit about what the spec cannot show: a change in units, defaults or ordering is invisible to a spec diff and must be called out in the changelog by hand.
Give customers the code change, not the description
Many breaking changes are mechanical: a renamed field, a moved parameter, a method that now takes an options object. For those, a codemod is worth more than any amount of documentation. Tools such as jscodeshift for JavaScript and TypeScript, or OpenRewrite for Java, let you ship a transformation customers run against their own code.
Design SDK upgrade paths deliberately
- Follow semantic versioning honestly. A major version bump should mean breaking changes, and a minor version should never contain one.
- Ship the new behavior behind an opt-in in a minor release before it becomes the default in a major one, so customers can migrate incrementally.
- Mark old methods deprecated in the type system (for example
@deprecatedin TypeScript or[Obsolete]in C#) so editors flag every call site for free. - Keep an upgrade guide per major version that lists every breaking change with a before and after snippet.
An SDK that pins its API version internally is also a migration tool: upgrading the package becomes the single, reviewable moment when behavior changes.
Open the pull request, with evidence attached
The step beyond a codemod is doing the change for the customer: opening a pull request against their repository that updates every affected call site. Dependency bots already do this for version bumps; the harder and more valuable version does it for behavioral changes that need real code edits.
An automated PR is only as useful as the reviewer's confidence in it. A diff alone asks the customer to trust you. A diff with evidence (which changelog entries it addresses, which call sites it touched and why, and proof that behavior is unchanged where it should be) asks them to check your work, which is a much easier request. The strongest form of evidence is traffic replay: run recorded real requests through the old and new code and show that the responses match, or show exactly where they differ and why that difference is intended.
Measure adoption per version, per customer
You cannot shorten what you do not measure. Log the API version (and SDK version, if you can get it from the user agent) on every request, and build a view of traffic by version, by customer, by operation. That tells you who is still calling the old behavior, which operations they depend on and whether a migration push is working.
- Track the share of traffic on each version over time, not just the number of customers who have upgraded.
- Watch for customers who upgraded and then rolled back; they found something your migration guide missed.
- Reach out directly to the long tail before the sunset date, with their specific affected operations in hand.
Providers who want to go further can offer migrations as a service to their own customers. Releo is being built for exactly that loop: detect the change, write the PR across every affected repository and verify it with replayed traffic. It is in private beta.
Frequently asked questions
What should an API changelog entry include?
The exact operations and fields affected, whether the change is breaking, the version it ships in, the sunset date of the old behavior and a link to a concrete migration path. A structured copy of the same data lets customers filter it automatically.
Are codemods worth building for API changes?
For mechanical changes such as renames and moved parameters, yes. One codemod replaces the same manual edit across every customer codebase. For semantic changes, a codemod helps but still needs behavioral verification.
How do I know when it is safe to sunset an old API version?
When traffic data shows the remaining callers are few, known and contacted. Measure requests per version per customer and operation, and do not rely on a fixed calendar date alone.
Related guides
- How to migrate to a new API version safely
- How to deprecate an API
- OpenAPI diff: detecting breaking changes in CI