API Versioning
API versioning lets you evolve your API while existing clients keep working. The goal isn't to version often — it's to version rarely, by making most changes additively, and to have a clean, well-communicated path when a breaking change is truly unavoidable.
The mental model that saves the most pain: a version bump is a cost you impose on every client, so earn it. Add before you change, and change before you break.
TL;DR
- Version only for breaking changes; make everything else additive.
- URL path versioning (
/v2/...) is the most common and visible strategy. - Support 2–3 versions at most during a transition.
- Announce deprecations with a timeline and a
Deprecation/Sunsetheader.
Quick Example
URL path versioning — old clients keep hitting v1 while v2 ships breaking changes:
Core Concepts
Breaking vs non-breaking
Design clients to be tolerant readers (ignore unknown fields) so additive changes never break them.
Version lifecycle
- Active — fully supported.
- Deprecated — sunset date announced; still works.
- Retired — removed.
Versioning Strategies
URL versioning is the pragmatic default for most public APIs.
Best Practices
Version sparingly and clearly
Start at v1 (never v0), bump the major version only for breaking changes, and keep at most 2–3 active versions with migration guides.
Run a real deprecation process
- Announce the deprecation and a sunset date.
- Add a
Deprecation(andSunset) response header. - Log usage of deprecated endpoints.
- Reach out to high-volume clients directly.
- Retire only after the sunset date.
Common Mistakes
Versioning for additive changes
Breaking a version in place
FAQ
When should I create a new API version?
Only for a breaking change you can't avoid — removing/renaming fields, changing types, or altering auth. Additive changes (new optional fields, new endpoints) should ship into the current version without a bump.
Which versioning strategy is best?
URL path versioning (/v2/...) for most APIs: it's explicit, easy to route, and easy to test. Header/media-type versioning keeps URLs clean but is harder to discover and debug. Query-param versioning is simplest but the least clean.
How many versions should I support at once?
Two or three active versions during a transition. More than that multiplies testing and support cost. Use a clear deprecation timeline to retire old versions.
How do I avoid versioning altogether?
Make changes additive and design tolerant clients that ignore unknown fields. GraphQL takes this further — clients request only the fields they need, so the schema can evolve without versioned endpoints. See GraphQL.
Related Topics
- REST API Design — Evolvable endpoint design
- API Design Best Practices — Additive-first evolution
- API Documentation — Documenting versions and deprecations
- GraphQL — Schema evolution without version bumps