Clean • Professional
API Versioning is the practice of managing changes to an API without breaking existing clients.
As APIs evolve, versioning ensures backward compatibility while allowing new features and improvements.
API Versioning Strategies are different approaches used to manage changes in an API over time without breaking existing clients.
When an API evolves—new fields are added, response formats change, or endpoints are modified—older applications (web, mobile, third-party clients) may still depend on the previous behavior. Versioning strategies allow both old and new versions of an API to coexist safely.
In simple words :
API versioning is the practice of assigning versions to an API so changes can be introduced without affecting existing users.
Without versioning:
With versioning:
There are 4 widely used API versioning approaches.
Version is included directly in the API URL.
Example
/api/v1/users
/api/v2/users
Spring Boot Example
@GetMapping("/api/v1/users")
public List<User>getUsersV1() {
return userService.getUsersV1();
}
@GetMapping("/api/v2/users")
public List<UserV2>getUsersV2() {
return userService.getUsersV2();
}
Flow
Client → /api/v1/users → Controller v1
Client → /api/v2/users → Controller v2
Pros
Cons
👉 Best choice for beginners & production APIs
Version is passed as a query parameter.
Example
/api/users?version=1
/api/users?version=2
Spring Boot Example
@GetMapping(value = "/api/users", params = "version=1")
public List<User>getUsersV1() {
return userService.getUsersV1();
}
@GetMapping(value = "/api/users", params = "version=2")
public List<User>getUsersV2() {
return userService.getUsersV2();
}
Pros
Cons
Version information is sent in the HTTP header.
Example
X-API-VERSION:1
X-API-VERSION:2
Spring Boot Example
@GetMapping(value = "/api/users", headers = "X-API-VERSION=1")
public List<User>getUsersV1() {
return userService.getUsersV1();
}
@GetMapping(value = "/api/users", headers = "X-API-VERSION=2")
public List<User>getUsersV2() {
return userService.getUsersV2();
}
Pros
Cons
Uses the Accept header with a custom media type.
Example
Accept: application/vnd.company.app-v1+json
Accept: application/vnd.company.app-v2+json
Spring Boot Example
@GetMapping(
value = "/api/users",
produces = "application/vnd.myapp.v1+json"
)
public List<User>getUsersV1() {
return userService.getUsersV1();
}
@GetMapping(
value = "/api/users",
produces = "application/vnd.myapp.v2+json"
)
public List<User>getUsersV2() {
return userService.getUsersV2();
}
Pros
Cons
| Strategy | Version Location | Usage Level | Complexity |
|---|---|---|---|
| URI Path Versioning | URL (/api/v1/users) | Most commonly used | Easy |
| Request Parameter Versioning | Query param (?version=1) | Moderately used | Easy |
| Header Versioning | Custom HTTP Header (X-API-Version) | Common in enterprise APIs | Medium |
| Media Type Versioning | Accept Header (application/vnd.app.v1+json) | Less common but REST-compliant | Hard |
Choosing the right API versioning strategy depends on who consumes your API, how stable it needs to be, and how closely you follow REST standards. Below are the most practical and commonly used choices in real-world Spring Boot applications.
Recommended Versioning Strategies
| Scenario | Best Strategy | Why It Works |
|---|---|---|
| Public REST APIs | URI Path Versioning (/api/v1/users) | Simple, visible, client-friendly, widely adopted |
| Internal APIs / Microservices | Header Versioning (X-API-VERSION) | Clean URLs, flexible, good for controlled systems |
| REST-Pure / Enterprise Systems | Media Type Versioning (Accept header) | Most REST-compliant and future-ready |
| Simple / Learning Apps | URI or Request Parameter (?version=1) | Easy to implement and understand |
Client v1 ──► API v1 ──► Works
Client v2 ──► API v2 ──► Works
Old clients unaffected
API Versioning is essential for scalable and reliable APIs.