Analysis Of Web API Versioning Options
Refering to a questions over versioning conventions used OpenStack Api, Mark Nottingham provides an analysis of the various strategies for versioning Web API in the cloud. In comparing software versioning to versioning on the web he says, that the software versioning has evolved and in general well understood.
Developers are used to software versioning; e.g., for every release, you bump an identifier. There are usually major versions, minor versions, and sometimes things like package identifiers.
This fine level of granularity is useful to both developers and users; each of these things has precise semantics that helps in figuring out compatibility and debugging.
However, this idea of versioning, he says, doesn’t translate very well to the versioning on web API’s.
[clients] holding onto a link from the previous version of the API has to decide what to do with it going forward; while they can guess that there’ll be compatibility between the two versions, they can’t really be sure, and they’ll still need to be rewriting a bunch of APIs.
[…] just sticking software versions into Web URL removes a lot of the value we get from using HTTP, and if you do this, you might as well be using a ‘dumb’ RPC protocol.
According to Mark, the theme of versioning on the web is preserve compatibility with existing clients.
The fundamental principle is that you can’t break existing clients, because you don’t know what they implement, and you don’t control them.
Additionally he points out that
[…] versioning [on the web] is inherently non-linear. In other words, every time you mint a new identifier, you’re minting a fundamentally new thing, whether it be a HTTP header, a format identified by a media type, or a URI. you might as well use “foo” and “bar” as “v1” and “v2”.
He provides various techniques with examples on how one might take advantage of extensibility mechanisms using http headers, and advocates identifying and resolving implementation problems using product tokens.
He classifies versioning on the web into two categories; representation format changes and resource changes.
Representation format changes have been covered fairly well by others (e.g., Dave), and they’re both simple and maddeningly complex. In a nutshell, don’t make backwards-incompatible changes, and if you do, change the media type.
Resource changes on the other hand are a more interesting problem according to mark. The tried and tested approach to versioning that’s commonly adopted is versioning the Uri. The less commonly adopted approach is using hypermedia.
RESTafarians have long searched for signs of HATEOS in Web APIs, and Roy has lamented its absence in the majority of them.
His article gives examples of how one might use hypermedia the expose meta-resources that could aid the clients in generating the uri’s by providing templates to the various resources the service provides.
In this manner, you don’t need a different URI for your interface, ever, because the entry point is effectively used for agent-driven content negotiation.
He concedes there are arguments for and against using HATEOAS, but the extensibility that the solution provides makes a strong case for using it as a strategy.
The key insight here, I think, is that URIs are used for so many things — persistent identifiers, cache keys, bases for relative resolution, bookmarks — that overloading them with versioning and extensibility information as well makes them worse for all of their various purposes. By pushing these concerns into link relations and media types using HATEOS, you end up with a flexible, future-proof system that can evolve in a controllable way, without giving up the benefits of using HTTP (never mind REST).
The original analysis can be found at his website.
Ralph Winzinger Nov 25, 2014