Versioning an API you cannot take down
You need to change a public API used by clients you do not control and cannot force to upgrade. Some are mobile apps that will run unpatched for years.
What are your options, and what would you actually do?
Solution
Start by asking whether the change is breaking at all. Adding an optional field, adding an endpoint, or adding an enum value a client can ignore are all additive and need no version. Most changes people reach for a version number over are additive, and treating them as breaking is how an API ends up with six live versions and nobody willing to delete any of them. The strongest first move is to make the change backwards-compatible instead.
If it genuinely is breaking:
- URL path versioning (
/v1/,/v2/). Ugly and un-RESTful — the resource has not changed, only its representation — but obvious in logs, trivially routable, and easy to explain. This is what most public APIs do, for exactly those practical reasons. - Header versioning (
Accept: application/vnd.example.v2+json). Cleaner conceptually, and harder to test by hand, cache correctly, and debug from a log line. Correctness losing to ergonomics. - Field-level evolution. Never remove or repurpose a field; add a new one and deprecate the old. The most sustainable option and the least dramatic, and it handles a surprising fraction of real changes.
What I would do. Path versioning for genuinely breaking changes, additive evolution for everything else, and a hard rule that a field's meaning never changes under an existing name. Silently repurposing a field is the worst outcome available: every client keeps working and every client is now wrong.
The part people forget: a deprecation process. A version with no retirement plan is permanent. That means instrumenting per-version and per-client usage from day one so you know who is actually affected; a published sunset date with Deprecation and Sunset headers on responses; direct contact with the remaining heavy users; and — for mobile clients that may never upgrade — accepting that some versions are supported for years, which is an argument for having as few of them as possible.
Brownouts are worth mentioning: deliberately failing the deprecated version for short windows before the sunset, so the clients still on it discover the problem while you are watching rather than on the retirement date.
The follow-up they will ask
Six months after the sunset date, 3% of traffic is still on v1 and it is one large customer. What now?