Pattern Sections
Pattern: Semantic Versioning
a.k.a. Version Number Triplet, Three-Number Version
Context
When publishing Version Identifiers (dynamically via API payloads) or featuring versioning in the API Description, it is not necessarily clear from a single number how significant the changes between different versions are. As a consequence, the impact of these changes is unknown and has to be analyzed by every client. Consumers would like to know the impact to plan the migration to the new versions beforehand and without investing much effort into their own analysis. In addition, providers must manage different versions and thus have to know whether the planned API interface and implementation changes are compatible or break client functionality in order to fulfill any guarantees made to clients.
Problem
How can stakeholders compare API versions to detect immediately whether they are compatible?
Forces
In the context of change management and API versioning, the following forces apply, which must be addressed by the Semantic Versioning pattern:
- Minimal effort to detect version incompatibility (especially for the client).
- Clarity of change impact.
- Clear separation of changes with different levels of impact and compatibility.
- Manageability of API versions and related governance effort (e.g., approval processes, quality gates, number of parallel versions, number of branches of API versions).
- Clarity with regard to evolution timeline of the API.
Pattern forces are explained in depth in the book.
Solution
Introduce a hierarchical three-number versioning scheme
x.y.z
, which allows API providers to denote different
levels of changes in a compound identifier. The three numbers are
usually called major, minor, and patch versions.
Sketch
A solution sketch for this pattern from pre-book times is:
Example
A start-up wants to establish itself as a stock exchange data provider in the market. In its first API version (called Version 1.0.0) the API offers a search operation, which can search for a substring of the stock symbol and returns the list of matching stocks including their full names and their prices in USD. Upon customer feedback the start-up decides to offer a historic search function. The existing search operation is extended to optionally accept a time range to provide access to the price historical records. If no time range is supplied, the existing search logic is executed and the last known quote is returned. This version is fully backwards compatible with the old version, i.e., old clients can call this operation and interpret its results. Thus, this version is called Version 1.1.0. Due to a bug in the search, not all stocks containing the supplied search string were found but only those starting with this string. The API implementation is fixed and rolled out as Version 1.1.1 international customers are attracted to the serviced offered by the start-up and request the support of international stock exchanges. As such the response is extended and a currency attribute is now supplied back. This change is incompatible for the client and thus the version is called Version 2.0.0.
Please note that this example is technology-independent on purpose. The supplied data can be transferred in any format, e.g., as JSON or XML objects, and operations can be implemented using any integration technology because this pattern deals with the conceptual problem of issuing version numbers based on the type of change introduced to the API interface or implementation.
Are you missing implementation hints? Our papers publications provide them (for selected patterns).
Consequences
The resolution of pattern forces and other consequences are discussed in our book.
Known Uses
The patterns is in widespread use, in the context of remote APIs and other software artifacts:
- A large Swiss finance institution uses Semantic Versioning for expressing the compatibility of their internal services. Major and minor version are exposed via the namespace while the fix version is only part of the contract documentation and is a time-stamp of the latest change.
- Terravis Berli, Lübke, and Möckli (2014) uses Semantic Versioning in its service contracts to all parties in order to express compatibility of its external services: major and minor version are exposed via the namespace, while the fix version is only part of the contract documentation. Compatibility between minor versions is achieved by transforming incoming and outgoing messages. This achieves compatibility in the case of minor versions, which would otherwise be broken due to a changed namespace. Furthermore it is possible to introduce changes that also restructure message contents (e.g. renaming fields or adding a new hierarchy) as long as the same information and the underlying conceptual model remains the same. The transformation can re-arrange the data accordingly.
- The eBay RESTful API uses three-number semantic versioning and combines this with Aggressive Obsolescence: a new major version remains compatible with an old one, but can deprecate functionality which in the future will be removed. This allows for an easier migration from the point of view of a client although the full version number is visible. However, eBay expects the clients to then migrate within the next six months to the new major version and remove the dependency on deprecated functionality.
More Information
Related Patterns
Semantic Versioning requires a Version Identifier. API Description and/or Service Level Agreement can carry the versioning information that matters to clients.
All life cycle patterns are related to this pattern (Eternal Lifetime Guarantee, Limited Lifetime Guarantee, Two in Production, Aggressive Obsolescence, and Experimental Preview). These patterns differ in the level of commitment given by the API provider; semantic versioning helps to distinguish past, present, and future versions.
In order to improve compatibility between versions, especially minor ones, the Tolerant Reader pattern can be used, see Daigneau (2011).
Other Sources
More information on implementing Semantic Versioning can be found online at Semantic Versioning 2.0.0.
For additional information on how to use semantic versioning in REST, the “REST Cookbook” includes a chapter on versioning. The “API Stylebook” also covers governance and versioning.
The Apache Avro 1.9.3 specification distinguishes the writer’s schema from the reader’s schema, and identifies the cases in which these schemas match and are not interoperable. The latter cases indicate incompatibility and/or interoperability issues, requiring a new major version.
James Higginbotham provides advice regarding “When and How Do You Version Your API?.
A structure and semantics for schema versioning is introduced in a blog post from Snowplow. It utilizes the three version numbers of this pattern, specifically defining their meanings in the context of data structures. The first number is called “model” and is changed if all data readers break; the second one is the “revision”, which is incremented if some data readers break; the last is called “addition” and is incremented if all changes are backwards-compatible.
LinkedIn defines breaking and non-breaking changes in its “API Breaking Change Policy.