Evolving RESTful services using fine-grained versioning

December 26, 2016 REST

So you created a kickass API that's conquering the world! The chances are that you have created a frontend using -- insert cool javaScript framework of the day -- which is communicating with -- insert hipster backend framework -- using the well-known principles of RESTful services. Or might you have used REST to replace SOAP in your existing infrastructure?

Anyways, your API is working fine. However, we aren't the only mushroom in the forest! We need to adapt and quick!
Now comes the point where we start worrying about versioning.
One might have chosen to add a version number to the URL of your API and created formal contracts using RAML files, swagger, or something shiny. And tada! We have our versioning systems! But wait, this looks like... SOAP?

Ok, but what's the problem, why create this fuzz?
Well, when you are in a highly competitive business you want to ship your features as fast as possible. Restricting yourself to a single formal contract for the whole API is blocking your velocity. Let me explain; an API probably has to change due to a new feature, change request, or a bug. All those changes are happing concurrently; some finish in time; others fail to deliver. Adding the fact that changing an API also affects the consumer, who also has to adopt it, this starts to look more like a recipe for disaster. Things start to get blocked, and every participant is pointing in a different direction.

So, are we doomed?
Not really—when using RESTful services, you can negotiate the contract between two parties for a single operation
by making use of the HTPP "Content-Type" and "Accept" header.
Probably, you are currently using those headers to distinguish requests and replies in JSON or XML. But, imagine that a client adds the "Accept: application/json;V1.0" header to its request. In this case, the server sees the consumer is interested in a JSON response complying to version V1.0. It can either reject this version or send a reply including the "Content-Type: application/json;V1.0" header.
We can apply the same logic for sending data to the server.

This approach gives us the power to version operations instead of the whole API. Isn't this nice? Let's call if fine-grained versioning!

Yes, okay, but aren't we adding a lot of work?
Indeed, your (public) API will have to add some logic to make this approach work. Luckily, we have the tools to do this, for instance, AWS API Gateway. However, I believe that adding this arguable complexity outweighs the disadvantages of having one single API version.

When your API is changing, you probably will need to take in mind consumers that upgrade at a different pace. Using fine-grained versioning, we only need to bump the version of the operation that is affected. Doing this reduces the time from implementation till production.

I've written a follow-up blog post which demonstrates this technique.

Jeroen Bellen
Jeroen Bellen