Release management is an important part of any API development lifecycle. That being said, it is also consistently overlooked, often considered more as an afterthought than a foundational element of the API and business environment. This is unfortunate, as implementing proper release management can not only prevent significant issues from arising, it can also improve the efficacy and value of your customer relationship management processes.
Today, we’re going to look at two approaches to release management. We’ll discuss versioning and revisioning, and isolate some specific circumstances in which each is appropriate. Some of our definitions are inspired by the work of Darrell Miller, who has come to define the revision concept as it relates to API versioning.
The principle idea behind versioning is that each group of related changes to an API is presented under a specific number, often denoting what type of release it is. Typically, the first number denotes a major release and marks a major change to the codebase that often alters functionality or has a significantly different type and amount of support over other versions. The implication is that what works in 2.0 may not have any support in 1.0 due to the difference between the codebase.
The secondary numbers, and further numbers after that, typically denote smaller changes, and in fact, often represent sub-versions of the main core version. For instance, “Version 1.1” might indicate that it is a minor revision of the first version of the codebase. Going further, “Version 220.127.116.11” might denote that it is the third patch to the second update to the second minor revision of the first major codebase version. You can clearly see that while the numbering system could get very complex, organizing the numbers in a very clear manner helps users understand even the most dense naming scheme at a glance.
A big takeaway for versioning is that it doesn’t itself prevent code that breaks functionality, it just makes it obvious when it occurs and allows the user to predict and plan.
Revisions, unliked versioning, are all about preventing code that breaks from version to version. A revision is just that – a small change to the API over time that allows for morphed functionality and purpose without fully breaking the API itself. When a revision is made to the codebase, that revision is considered the current, authoritative code source, and is made the primary code for all implementations. Each change behind that, however, is still valid and is considered “legacy”.
The chief difference between versioning and revisioning, then, is that each change is incremental from beginning to end. While versioning has revisioning integrating into the minor phases from 1.0 to 1.x, whatever the last stage may be, revisioning is entirely incremental to prevent code and function breaking.
Why This Matters
What this all comes down to is a simple dichotomy – revisions are incremental, non-breaking changes to an API, whereas versions are often-breaking, major changes. Due to this dichotomy, each approach has a very specific use case. When an API is flexible enough to support version 1.0 as a legacy option while transitioning to 2.0, versioning is a good idea. Users understand exactly what the expectations are, what the code base actually means, what each number represents, and what the limitations of support actually are.
Additionally, when an API is only useful as a conduit to another API or system, in those cases it makes more sense to have a single 1.0 that is supported, used, then deprecated, forcing a break. In these cases, the functionality of the API itself is not the value, its the integration – thus, when the integration no longer works and requires a breaking change, forcing the client to update is the best approach.
Of course, not everyone can support that sort of user flow, and in those cases, revisioning is much more acceptable. When the API absolutely must be up and running without any changes to the codebase, such as when an API supports vital business functions, medical purposes, security systems, etc., a break in function is completely unacceptable, and more to the point, the design process of such critical functions should never call for such breaking functionality in the first place.
Opting-In and Transparency
It should be noted that this conversation has more than one solution outside of the versioning/revisioning dichotomy. While versioning and revisioning are both great solutions to the issue of iteration control, there is the underlying problem that users may not actually want these changes at all.
This arises from faulty communication with the developer user but can be effectively managed by adopting a simple opt-in method of consent. Users can be offered the ability to choose between the stable offering and the “breaking” change. This can be done at any level, really, and is more an organizational choice than anything.
In a versioning environment, this looks like a multi-supported system of branches. Having an experimental branch, a stable branch, and a rolling update branch can ensure that users who opt out of major changes can use legacy offerings while new users who want additional features can opt into those features and the associated risk of broken functionality. This could also mean having a “legacy API” and a “current API”, with the caveat that the legacy API won’t receive updates and has limited technical support on offer.
Revisioning is already in many ways an opt-in process as long as users are allowed to use previous revisions. Key to both of these process is transparency – the idea that the user is made aware of the possibilities and risks before making their choice. Accordingly, documentation is huge here and should be considered principle to the solution no matter which route is taken.
Why Release Management is Important
Before we get into the differences between revisioning and versioning, we should discuss why release management, in general, is an important element of successful API design. Release management as a concept is simply the idea that each change to the API should be categorized, known, and displayed to the user for improved understanding, discoverability, and usability. Ultimately, release management allows developers to have complete control over the release of each build and serves thus as both a management and a communication tool.
Release management brings users a great many benefits, but perhaps even more important is not what it enables, but instead what it prevents – breaking changes. When code is sent to the user that breaks the core functionality of the client application, this type of change can result in users who are completely cut off from their required services. With strategic release management, communication of changes aligned to the long-term functions and goals of the organization can effectively be communicated to the userbase, thereby preventing many of these issues from ever occurring.
Of course, this also means the organization can benefit from this single source of truth as well. Aligning organizational efforts (i.e. supporting version 2.0 and deprecating version 1.0) alongside the single source of truth and integrating user communication into the process can help maintain usability while also promoting better function. In other words, with this single source of truth, everyone understands what iteration is currently supported, what iteration is not, what those iterations do, and what was changed to make the current iteration what it is (alongside data on who actually made that change).
The problem with this process is that it seems that many people think iteration and release management can just simply be arbitrarily set and managed. The reality is that the system only really works if its structured – otherwise, it’s just a very organized form of chaos. To this end, we can look at two very powerful options for release management – versioning and revisions.
Ultimately, this is a fundamental design choice that should be made early on when an API developer knows changes are going to be something that’s done. Revisions are great as they prevent breaking changes to the codebase, but they limit what developers can do in a given timeframe as each change must be incremental. Versioning, on the other hand, allows you to do whatever whenever you want, but also increases frustration in the user base and could break critical client systems if the change isn’t planned effectively.
What this really comes down to is what your relationship with the client is. If you issue changes directly to a client and don’t mind breaking function, then versioning is your choice, especially if the client is not doing something so critical that short breaking changes would result in catastrophic failure. However, if you need a softer touch, this is obviously not appropriate, and revisioning is a better choice – this is especially true if your API has regulatory concerns, drives medical appliances, etc.