In this article, we will cover how to Design API that have multiple version and when they are needed.
Here’s a link to the first part related to API Naming Conventions
If these are useful or need improvement or you find something which does not look right, please do share your valuable feedback.
A live project is constantly evolving with new functionality being added daily resulting in constant changes at the API layer
The below aspects of an API can change over time
- Path parameter
- Query parameter
- Headers
- Payload: Request/Response
- Database schema changes
- Change in business logic like new integration or new validations
- External dependencies (APIs, etc.) change
- Endpoint to be changed (extremely rare)
API Versions
- Time to integrate
External consumers of your API need time to adapt to the changes
- Deployment dependencies
It is ideal to support backward compatibility for our APIs because of deployment delays that can occur between microservices and dependencies.
This practice should be followed even if all applications are developed by the same team
Designing API Version
Database
Here’s a ready reckoner

Code
- Feature Flags
Enable features flags using Environment variables
- Using path parameter like “v1”, “v2” helps to identify the version of API being invoked.
Here’s a Decision Matrix that will be helpful

Impact on application code
Let’s take an example to understand better. Listed below are the most common packages in most applications
- com.company.api.v1.controller
- com.company.api.v1.dto
- com.company.api.v1.dto.mapper [ DTO to Model mapping. Idea being service layer only deals with Models ]
- com.company.api.v1.dto.validator [ input sanitization and validation ]
- com.company.service [ business rules/validations and persistence logic ]
- com.company.dao
- com.company.model
Let’s see how to bring the above aspects to life via our application code
For any changes to Path/Query Parameters, Headers and Request/Response Payloads it’s best to add new packages per version
- com.company.api.v[n].controller
- com.company.api.v[n].dto
- com.company.api.v[n].dto.mapper
- com.company.api.v1.dto.validator
Modify models if these changes trigger changes into model layer
- add to current model
- extend current model for the next version
- create a new package and model
For changes to business logic, depending on the change we can
- It would be ideal to add to the same function if we have feature flag protected changes
- create a new function in same Service class
- create a new package/class to map to v2 packages in other layers
To minimize code duplication and maximize code reuse it is best to create separate packages
Clean up
Ensure that old un-used code from past versions are periodically cleaned up to avoid lots of unused code flows.
Conclusion on API Version Design
Hope the details were helpful and meaningful to help you derive a strategy that works for your projects.