When it comes to creating APIs, developers face the eternal dilemma: how can we ensure they are sufficiently stable and reliable, while allowing for the flexibility our (internal and external) customers have come to expect? The versioning approaches below might help.
Finally, I’ll propose a versioning strategy which I consider the best fit for “general purpose” use.
An API forms a ‘contract’ between two systems, therefore it should be:
However, user needs and business goals change, so APIs must be adaptable and gracefully allow for modifications to their behaviour. The simultaneous need for stability and change seem completely incompatible with one another. This is where API versioning comes in: We bind a contract to a version indicator so clients can expect a stable API and developers can make updates to their service.
Several API versioning strategies exist:
There is no set standard for API versioning and all of these methods are currently in use in production systems across the web.
This is explained in part by the requirements an API producer might have for their API:
- Usable by a browser: No header versioning (in-path versioned URLs need no additional data for fully defining a contract)
- Semantic correctness: No in-path versioning (when strictly adhering to REST is required)
- Adaptability: Query path (so other configuration parameters can be appended as well — see AWS)
- Ease of development: No versioning (when there is relative certainty about no new version ever being required)
From this, we can conclude lifespan and complexity are the two main factors in deciding how versioning should be implemented.
1.2 RESTful vs. practical
A common argument against placing version indicators in the URL is that it breaks compatibility with the RESTful standard. This is because the version of a resource gives no information about the resource itself. The API’s history tells us nothing about what we’re accessing.
Nevertheless, versioned URLs also provide quite a number of benefits:
- Visible to developers: there’s no ambiguity
- Usable across every device and interface: browsers and API clients alike can both access the resource
As a middle ground, an API producer might alias the latest stable version (
/api/v2/...) to a version-less scheme (
/api/...). This keeps URLs clean but still allows clients to choose whether or not they want to fix their implementation to a specific version or simply the latest version.
1.3 Combining versioning methods
If time and resources are available, multiple ways to indicate a version could be implemented. This would allow the client to choose when to use which strategy. As an additional benefit, API clients can access resources completely RESTful while browsers can use a path-based alternative.
1.4 Types of versioning
A version number is not the only way in which an API version can be specified (merely the most common one). For example, Twilio uses timestamps instead. This might be a good approach for agile development environments where daily updates to an API are common: in such a case, the version would simply be the deployment day/week/month.
1.5 Continuous versioning
In some extremely agile environments, even using a timestamp as a version number is not sufficient to keep up with the rate of change. In such a case, a development team can choose to adopt continuous versioning (CV). This essentially means APIs aren’t fixed to a specific version but instead communicate their capabilities to a client on a per-resource basis, allowing the client to forge a request based on both available and requested features simultaneously.
Nordic APIS has a great blog on how Badoo implemented this strategy. As the title of their blog post suggests, this type of agility is mostly geared towards internal APIs where decisions and agreements can more easily be made. Having control over both client and server certainly makes CV much more straightforward to implement.
In most cases, path-based versioning in combination with a version number format would be the best choice. This method provides discoverability, extensibility and universal usage. Furthermore, this method also seems to have the most industry support: Google, Dropbox, Foursquare, Stripe, etc. are all in favour of this strategy.
Deciding if and how to version should be a pre-emptive choice: once an API is put into use, we implicitly create a contract with all clients using it. If versioning is not embedded in the API scheme by that point, we are severely limited in choice if we don’t wish to break backwards compatibility.
Continuous versioning along with content negotiation through feature flags is also a worthwhile path to explore for agile projects.
Ultimately, it’s of much greater importance to have a well-documented and stable API. API versioning strategies are nothing more than an aid in achieving those goals.
1.7 Further reading
- API Stylebook: Updates and Versioning
- Best practices for API versioning?
- What Makes a Great Open API?
- Ain’t Nobody Got Time For That: API Versioning
- Your API versioning is wrong, which is why I decided to do it 3 different wrong ways
- Introduction to API Versioning Best Practices
- Continuous Versioning Strategy for Internal APIs