This is a very lively topic.
The starting point for these questions must be: in our world (enterprise grade computer science), what isn’t versioned? The answer to that is: everything is versioned.
Therefore, the actual question splits into two parts:
1) What makes REST and micro-services so special that they don’t get versioned? The answer here is easy – nothing. They must be versioned, just like everything else.
One post (here) tries to convince others of “versioning only as a last resort”. This book tries to convince others that “just monitoring the logs” is a sufficient solution to the problem. This is all amateur-hour stuff. Just ignore them.
Now that we know it must be versioned, the actual question arises:
2) How should the versioning be implemented in REST and microservices?
The choices seem to be:
1) URL: (e.g. http://yourapp/v1.2.3/person…)
2) URL parameter: (e.g. http://yourapp/person?Version=1.2.3)
3) Header – custom (e.g. “X-Api-Version: v1.2.3”)
4) Header – Accept (e.g. “Accept: application/yourapp.v1.2.3”)
5) Payload (e.g. inside the JSON { “version” : “v1.2.3”, “name” : “joe”, … } )
6) Hostname: (e.g. http://v1.yourapp/person)
People argue against #1 with strange arguments like a URL “represents a person” or “the idea of a person”. It is strange because “person” is not, and can not, be a universally workable concept. (Quick test if you are not convinced – write client side code that receives person JSON data, and computes the total of that person’s age and height. It can’t be done, for multiple reasons: you don’t know the keys and you don’t know the units. What if “age” is actually “bornAt” as milliseconds since the epoch?) The genius Roy T. Fielding simply got it wrong for the enterprise – a resource is a universal construct only in a university classroom. And, “Controls have to be learned on the fly” may eventually work once machines take over, but for now, even “age plus height” can’t be learned dynamically.
So – there just isn’t A concept of a person. There must be some implementation behind it, and that implementation needs to be versioned. Because in the enterprise world, something always changes.
The argument against #3 and #4 is a variation of the above: the URL “http://yourapp/api/person” makes it look like “person” is universal. But it is not universal. So the URL is a lie. It must be versioned.
The argument against #5 is the “surprise!” factor. Your client application had link to a person, but the data came back 3 versions in the future, and your client application has no mechanism available to “correct” the request, unless #1-#4 is provided. It’s the “box of chocolates” style programming – you never know what you’re going to get.
Since #6 is basically #1 with the “v1” moved to the left so much that it ends up in the DNS of the hostname, is shares the advantages. However, it proposes an uncomfortable use of DNS. And it ties the concept to a particular hostname (or pattern of hostnames, like “v2.stage.app.com”, “v1.prod.app.com”, etc.) In the end, it seems like a personal preference that a REST server should respond to requests without needing to know its DNS entry. (Or worse, creating option #4a: “Look for a version in the ‘Host:’ header of the request”).
One clever variation is just: do more than one! It seems like extra work, and you have to worry about conflicts (like 3 different versions in the same request). But, it does ensure that everybody yells at you equally 🙂
There are plenty of enterprise-grade APIs that use #1. They do differ on /v1/ versus /v1.0.0/, with the majority using the simpler /v1/.
* Dropbox – #1 (“/2/”), and is too embarrassed to document it
* Amazon – #2 (“/foo?Version=2012/01/02”)
* Twitter – #1 (“/1.1/”), also too embarrassed to document it
* Best Buy Developer API – #1 (“/v1”), also too embarrassed to document it
* Facebook – #1 (“/v2.5/”) with #3 in return (“facebook-api-version:v2.0″)
More links on versioning:
[showhide more_text=”Show Links” less_text=”Hide Links”]
– The cost of versioning an API
– Contract Versioning, Compatibility and Composability
– State Machines, Contracts and Versioning
– REST Versioning
[/showhide]
Quote from the book:
[showhide type=”book” more_text=”Show Book Quote” less_text=”Hide Book Quote”]
“Avoid Versioning Microservices and Endpoints”
“A microservice is not a library but an independent software application. Due to the fast-paced nature of microservice development, versioning microservices can easily become an organizational nightmare, with developers on client services pinning specific (outdated, un-maintained) versions of a microservice in their own code. Microservices should be treated as living, changing things, not static releases or libraries.”
My summary of that quote is “we are cowboy coders who can’t be bothered with puny details like versioning (or documenting, or up-time)”, i.e. amateur-hour again.
[/showhide]