REST API Versioning Strategies
Fast recall
Quick revision
Core answer
Interview-ready guide
Interview answer
API versioning gives existing clients a stable contract when the API must make an incompatible change. It is not a label for every deployment. Internal refactoring, an index, or a bug fix normally stays in the same version. Renaming or removing a response field, changing its meaning or type, or changing an accepted input can require a new version because deployed clients may still depend on the old behavior.
A compatible change can remain in the current version. For example, a new optional response field is usually safe when the published contract allows clients to ignore unknown fields. Replacing fullName with required givenName and familyName is different: old clients look for the removed field and new clients expect fields the old response never supplied. That change needs a compatibility plan, often a new version.
Path versioning, such as /v2/orders/42, is visible in links, logs, and routing, but creates a separate URI space. A query such as /orders/42?api-version=2 keeps the base path familiar but is easy to omit. A custom header or versioned Accept media type keeps the target path stable, although browser testing and documentation become less obvious, and caches must distinguish header-selected representations correctly.
Version 1 and version 2 should normally run together for a published migration period. The team releases examples and a change guide, measures which clients still use version 1, announces deprecation and retirement dates, and helps important consumers move. Only after that support window should version 1 be removed. This avoids forcing every mobile app or external integration to upgrade on the server's deployment day.
The syntax is less important than consistency and lifecycle ownership. Each supported version needs documentation, security fixes, contract tests, monitoring, and sometimes a separate boundary adapter. Too many versions slow delivery, while retiring one too quickly breaks consumers. I would keep business logic shared where possible, isolate version-specific request and response mapping, and create a new version only when compatibility cannot be preserved clearly.
REST API Versioning Strategies
Direct Answer
API versioning is a compatibility policy for changes that existing clients cannot safely consume. Common version signals are a path segment, query parameter, request header, or versioned media type. The important work is defining what counts as breaking, supporting overlapping versions, publishing migration guidance, and retiring versions deliberately.
Deep Dive & Architecture
A deployed service can change many times without changing its public version. Bug fixes, indexes, caching, and internal refactoring are implementation changes. A public version changes when the observable contract cannot remain compatible: accepted inputs, response meaning, status codes, authentication expectations, or important timing and ordering guarantees.
Path versioning creates distinct URI spaces and is easy for infrastructure to route. A query parameter selects a version within a familiar path. Custom headers and media-type parameters select behavior or a representation at a stable path. When a response varies on request headers, cache behavior must account for that selection; a server can use Vary to name the request fields that influenced the representation.
Supporting two versions does not require duplicating the whole application. A shared domain service can sit behind separate request and response adapters. That keeps version-specific translation at the boundary while business rules remain common. Contract tests should prove the old adapter continues to behave as published.
Retirement is part of design. Documentation should state supported versions, migration differences, and a date or policy for removal. Traffic metrics reveal active consumers, but silent traffic does not replace direct communication for important clients. Long-lived versions cost engineering effort, so a team should balance migration safety against indefinite maintenance.
Code Example
GET /orders/42 HTTP/1.1
Host: api.example.com
Accept: application/vnd.example.order+json;v=2
HTTP/1.1 200 OK
Content-Type: application/vnd.example.order+json;v=2
Vary: Accept
{"id": 42, "givenName": "Ada", "familyName": "Lovelace"}
Vary: Accept tells a cache that the selected response can differ by the request's Accept field. It does not by itself define the team's compatibility or retirement policy.
Check your understanding
Answer these without looking back at the article.
- Which API changes normally require a new version?
- What trade-off does header versioning create for caches and tooling?
- How can two API versions share the same business logic?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.