API Versioning and Evolution
Learn how APIs evolve without unnecessarily breaking existing consumers.
Breaking vs Non-Breaking Changes
API Evolution
Breaking changes can include removing fields, changing field types, changing semantics, removing enum values, changing authentication behavior, making optional inputs mandatory, or changing status-code behavior clients rely upon.
Non-breaking changes commonly include adding optional request fields and adding response fields when clients are designed to ignore unknown fields.
Compatibility must be evaluated from the perspective of real consumers, not only server code.
Add optional response fieldRemove response fieldChange string to objectVersioning Strategies
Common strategies include URI versioning such as /v1/users, query parameters, custom media types, and header-based versioning.
URI versioning is highly visible and easy to route and document. Media-type versioning is more aligned with representation negotiation but can be less discoverable. Header versioning keeps URIs stable but makes requests harder to inspect casually.
There is no universal best strategy. Choose a strategy based on compatibility requirements, tooling, deployment architecture, and consumer expectations.
/v1/usersAccept: application/vnd.example.v2+jsonX-API-Version: 2Deprecation and Migration
A mature API should not suddenly remove old functionality. Consumers need notice, migration documentation, compatibility periods, telemetry, and a defined sunset strategy.
Track which API versions and endpoints are still being used. A deprecated endpoint can emit deprecation metadata or documentation links while remaining functional during the migration period.
Versioning is not a substitute for good API evolution. The best APIs minimize unnecessary breaking changes.
- Versioning should solve real compatibility problems.
- Deprecation requires communication and observability.
- Backward-compatible evolution is preferable to constant version proliferation.