REST API Versioning Approaches
Change in an API is inevitable as your knowledge and experience of a system improve. Managing the impact of this change can be quite a challenge when it threatens to break existing client integration.
REST doesn’t provide for any specific versioning guidelines but the more commonly used approaches. Here we list the commonly used approaches and the pros and cons.
Common Versioning Approaches
Versioning through URI
Version is very explicitly defined as part of the API URIs, an example below
https://{dns_name}/{domain_name}/{version}/{resources}...dns_name could be api.abc.com for external facing APIs or prod.abc.internal for internal APIs, domain_name could be reading-inventory.version could be v1, v2, so on.A concrete example would be https://api.abc.com/reading-inventory/v1/quizzs/...
And the backend SpringBoot controller could have code to handle this
@GetMapping({"/v1/quizzes"})
public List<Quiz> getAllQuizzes() {
...
}
The REST API purist would argue that API URI is used to identify a resource, while version is an attribute of the resource. In practice, the resource is identified by the uri after versioning tag.
Versioning through Query Parameter
This approach makes versioning as part of the request parameter, either make one as required query parameter or provide a default version to catch all if this is an optional parameter. An example below
https://api.abc.com/reading-inventory/quizzs?version=v1
And the backend SpringBoot controller could have code to handle this
@GetMapping({"/quizzes"})
public List<Quiz> getAllQuizzes(@RequestParam("version") String version) {
// logic here to check the passed in version string and based on
// that process the request differently
...
}
This approach is highly used by Amazon, Google and Netflix.
Versioning through Accept Header
This approach requires the API clients to provide the version information through the Accept (request) header along with the content-type (media) in the response — it is the preferred way, as this helps to version APIs without any impact on the URI. An example below
Accept=application/quizzes-v1+json
https://api.abc.com/reading-inventory/quizzs // URI contains no version info
As part of response, it should contain the version info in Content-Type header field, something like this
Content-Type=application/quizzes-v1+json;charset=UTF-8
Versioning through Custom Header
This approach defines a new header that contains the version number in the request as part of request header itself. A custom header allows the client to maintain the same URIs, regardless of any version upgrades. This approach is similar to the previous. The customer header name could be any name. An example below
x-api-version=v1
https://api.abc.com/reading-inventory/quizzs // URI contains no version info
And the backend SpringBoot controller could have code to handle this
@GetMapping("/quizzesByCustomHeader")
public List<Quiz> getAllQuizzes(@RequestHeader("x-api-version") String version) {
// logic here to check the passed in version string and based on
// that process the request differently
...
}
The response should contain the version info in a custom header field, for example,
x-api-version=v1
Versioning via Redirect
This approach basically use HTTP code 301 to redirect the client to a different URI to make further request. HTTP code 301 in the response indicates to the client that the URI has been permanently removed and the new URI is in the response’s Location header. An example below
GET https://api.abc.com/reading-inventory/quizzes
Would get the following response
HTTP status code 301
Location=https://api.abc.com/reading-inventory/v2/quizzes
Upon receiving this, client understands the semantics by extracting the new URI from the Location header, turns around and issue the following
GET https://api.abc.com/reading-inventory/v2/quizzes
Comparisons
Currently there is no “Best Solution for Restful API Versioning”, pros and cons [1–3], as demonstrated by the infographic below,
Summary
It’s clear that every versioning approach mentioned above have its pros and cons. When you pick a specific versioning approach, think about what you have done so far, and what’s the best to meet your business need and have least development effort.
With that, we outline some of the versioning best practices below,
Versioning Best Practices
- Using a new version when the current implementation breaks the existing clients.
- Once backwards compatibility is broken, or dramatically changing what’s in place, it’s time to consider another version
- Recommend to support 3 versions, so if the current API version is v4, only v2, and v3 will be supported while v1 will no longer be supported. No need to introduce minor versions.