As APIs evolve, older versions must be supported while newer versions offer enhanced functionality. This is where API versioning becomes essential. Spring Boot doesnβt enforce any specific API versioning strategy, giving developers the flexibility to implement the method best suited to their use case.
In this post, weβll explore multiple ways to build versioned REST APIs in Spring Boot with working code examples.

π― Why Version Your API?
- Backward Compatibility: Ensures existing clients continue to work.
- Progressive Enhancement: Allows iterative improvement without breaking old integrations.
- API Lifecycle Management: Encourages cleaner evolution and deprecation strategies.
π οΈ Common API Versioning Strategies
- URI Versioning:
/api/v1/resource
- Request Parameter Versioning:
/api/resource?version=1
- Header Versioning: Custom headers like
X-API-VERSION: 1
- Media Type Versioning (a.k.a Content Negotiation):
Accept: application/vnd.company.app-v1+json
β 1. URI Versioning (Path-Based)
π Structure
1 2 3 4 5 6 7 8 9 10 11 12 |
@RestController @RequestMapping("/api/v1/users") public class UserV1Controller { @GetMapping public String getUserV1() { return "User API - Version 1"; } } |
1 2 3 4 5 6 7 8 9 10 11 12 |
@RestController @RequestMapping("/api/v2/users") public class UserV2Controller { @GetMapping public String getUserV2() { return "User API - Version 2"; } } |
β Pros:
- Easy to implement and understand.
- Works well with tools like Swagger.
β Cons:
- Versioning in URI may violate REST purity.
β 2. Request Parameter Versioning
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
@RestController @RequestMapping("/api/users") public class UserParamVersioningController { @GetMapping(params = "version=1") public String getUserV1() { return "User API - Version 1"; } @GetMapping(params = "version=2") public String getUserV2() { return "User API - Version 2"; } } |
Example Calls:
GET /api/users?version=1
GET /api/users?version=2
β Pros:
- Cleaner URIs.
- Allows version negotiation through query parameters.
β Cons:
- Slightly less intuitive than URI versioning.
- May complicate caching.
β 3. Header-Based Versioning
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
@RestController @RequestMapping("/api/users") public class UserHeaderVersioningController { @GetMapping(headers = "X-API-VERSION=1") public String getUserV1() { return "User API - Version 1"; } @GetMapping(headers = "X-API-VERSION=2") public String getUserV2() { return "User API - Version 2"; } } |
Example Headers:
X-API-VERSION: 1
β Pros:
- Cleaner URIs.
- Avoids cluttering endpoint URLs.
β Cons:
- Not easily testable in browsers.
- Requires header manipulation support from clients.
β 4. Media Type Versioning (Content Negotiation)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
@RestController @RequestMapping("/api/users") public class UserMediaTypeVersioningController { @GetMapping(produces = "application/vnd.kscodes.app-v1+json") public String getUserV1() { return "User API - Version 1"; } @GetMapping(produces = "application/vnd.kscodes.app-v2+json") public String getUserV2() { return "User API - Version 2"; } } |
Example Headers:
1 2 3 4 |
Accept: application/vnd.kscodes.app-v1+json |
β Pros:
- Allows clients to choose desired representation.
- Ideal for hypermedia APIs.
β Cons:
- More complex for clients.
- Difficult to discover or test manually.
π§ Best Practices for API Versioning
- Avoid overusing versions: Not every change requires a new version.
- Document clearly: Provide Swagger/OpenAPI documentation per version.
- Deprecate responsibly: Inform users before removing older versions.
- Combine strategies: You can mix URI with headers for flexibility.
π¦ Sample Project Structure
1 2 3 4 5 6 7 8 9 10 11 12 |
src βββ main βββ java βββ com.kscodes.apiversioning βββ UserV1Controller.java βββ UserV2Controller.java βββ UserParamVersioningController.java βββ UserHeaderVersioningController.java βββ UserMediaTypeVersioningController.java |
β Conclusion
API versioning is a critical part of building resilient, long-lasting services. Versioned REST APIs in Spring Boot is a flexible options to implement versioning depending on the use case. Choose a strategy that aligns with your client ecosystem, maintainability needs, and evolution plan.