Chapter 12 of 12
Choosing an API Versioning Strategy
One decision path from the change in front of you to the method, with the criteria that actually separate the options and the policy each one needs.
Everything in this guide comes down to a handful of decisions taken in the right order. This chapter puts them in that order, so a change in front of you turns into an action without re-reading the rest.
The decision path
One. Classify the change. Use the closed list in what counts as a breaking change. If nothing on it applies, and no value quietly changed meaning, then the change is additive and you can ship it. Verify against the live service afterwards that it really was additive.
Two. Look for the additive form. Most breaking changes have one, and backward compatible change covers the moves in detail. A parallel field, a new endpoint next to the old one, and an optional parameter with a safe default all avoid a version between them.
Three. Ask who is affected. If you can list every caller and reach them, then coordinate the change with them and skip the version entirely. If you cannot, or the callers are mobile clients, partners under contract or customers on quarterly releases, the version becomes your coordination mechanism.
Four. Pick the carrier, once. The choice in the table below is made once for the whole API and rarely revisited, because changing it later is itself a migration for every consumer.
Five. Set the end date at the start. A version with no retirement plan is a permanent obligation, so decide when it ends while you are still deciding to create it. The chapter on deprecation and sunset covers how to run that ending deliberately.
Picking the carrier
| If | Then | Because |
|---|---|---|
| The API is public with open signup | URL path | Visible in every log and ticket, caches with no configuration |
| Consumers are internal teams and services | Header | One address per resource, and you control the clients |
| Callers paste and share URLs | URL path or query | The version survives being copied into a browser |
| The contract changes often and customers pin for years | Date-based in a header | No argument about what deserves a major |
| You genuinely version representations, not resources | Media type | Content negotiation is what it was designed for |
| You are on a managed gateway | Whatever it supports natively | Fighting the platform costs more than the tidier option is worth |
If two rows apply and disagree, take the one about your audience, because visibility to people you cannot contact beats elegance that only you will appreciate.
The policies that matter more than the carrier
A strategy is not finished when the carrier is chosen, and these three answers are what consumers actually need.
No version supplied. Serving the latest silently upgrades every unversioned caller into your next breaking change, which is why most public APIs serve a fixed default instead. Rejecting the request outright never surprises anybody, and that suits internal APIs best.
An unknown version supplied. Fail with a clear error naming the versions that exist, because falling back to the nearest one produces the worst bug report you will receive all year.
Support window. State how long a version keeps working once a newer one ships. A published window is what lets a consumer plan, and its absence guarantees that every deprecation you announce arrives as a surprise.
What good looks like
Six months after the decision, a healthy setup has a few recognisable properties that have nothing to do with the carrier you picked.
Breaking changes are detected before merge instead of being reported by a consumer, and most releases turn out to be additive and need no version at all. Every live version has a retirement date that somebody has agreed to. Documentation, mocks and tests are bound to the version each environment actually serves, and the changelog says what a reader must do instead of what you did.
Where to go next
If you are choosing a scheme, read versioning strategies for the mechanics of each one. If you are deciding whether to version at all, read when it does not matter for the bill you would be signing. If you already run several versions, running multiple versions covers keeping them straight, and deprecation and sunset covers ending one.
In Routebase
The decision path above maps onto the workspace in the order you would take it. Comparing two versions classifies the change, and the release wizard shows what a promotion would do to consumers before you confirm it. The versioning strategy card sets the carrier and the default behaviour, while a deprecation plan carries the end date from the first announcement through to the sunset.
What ties them together is that the contract is one object rather than several copies. Documentation, mocks, tests and monitors derive from the published version, so a decision taken in the designer reaches every surface that consumers touch. The Spec Versioning guide is the place to start, and the API design feature page shows how specifications, branches and releases fit together.
Frequently asked questions
Which API versioning strategy should I use?
For a public API with an open audience, URL path versioning is the usual answer, because the version is visible in every log line and it caches without configuration. For internal and platform APIs, header versioning keeps one address per resource at the cost of needing a Vary header. For a product whose contract changes often while customers stay pinned for years, date-based versions carried in a header fit better than a counter.
How do you decide whether to version at all?
Classify the change first. If it is additive, ship it and verify that it really was additive. If it is breaking and every consumer is someone you can reach, coordinate the change instead of versioning it. Only a breaking change affecting consumers you cannot reach genuinely needs a new version.
Can you change an API versioning strategy later?
You can, and it costs your consumers a migration, so it belongs in the same category as a breaking change. Running both carriers for a transition period is the least disruptive route, since the server can accept a version from either place while clients move. Picking a strategy before the first external consumer arrives is much cheaper than changing it afterwards.
What policies does an API versioning strategy need alongside it?
Three, and they matter more than the carrier. Decide what happens when no version is sent, decide what happens when an unknown version is sent, and decide how long a version is supported once a newer one exists. Publishing those three answers is what turns a versioning scheme into something a consumer can plan around.
Last reviewed by The Routebase Team.