Application Versioning Strategies

Alexander Kozhenkov
Javarevisited
Published in
3 min readDec 27, 2021

--

Photo by Angèle Kamp on Unsplash

There are many ways to version applications. Some of them appeared a long time ago and have little sense in web development. Nevertheless, they continue to be used. In this article, we will consider the various versioning options, and in which cases they are appropriate to use.

Semantic Versioning

<major>.<minor>.<patch>[.<build number>] (1.20.11, 1.20.11.403)

  1. Major — increasing the major version usually breaks compatibility, allowing developers to remove the deprecated API or rework the existing ones. Users know about it and do not expect a smooth update.
  2. Minor — version increment implies adding new functionality without breaking compatibility.
  3. Patch — also known as bugfix version that includes fixing security vulnerabilities, etc.
  4. Build number — optionally, the build number can be additionally added.

Semantic Versioning (SemVer) is the most common versioning method, so it is used everywhere, including the web (for example, in versioning microservices). But the API itself on the web already has versioning, and clients see the version of the API, not the application.

SemVer is great for versioning libraries or, for example, databases. Thus, users will immediately know if they can upgrade painlessly.

Calendar Versioning

<year>.<month>.<patch> (2022.07.01)
<year>.<minor>.<patch> (2022.1, 2022.1.1)

Calendar Versioning (CalVer) is used when you don’t care about compatibility. For such cases, using SemVer leads to having the first digit 1 forever.

This versioning is especially great for on-premise software (e.g., IntelliJ Idea uses it), and it is the most meaningful for external users.

Sprint-based Versioning

<symbol><sprint number>[.<patch>] (M27, M27.1)

When the development process is based on Scrum sprints, and the release is rolled out following the sprint results, then a reasonable solution is to version the product based on the sprint number. The first character here helps you not to confuse this versioning strategy with all the others. If a hotfix is needed for the latest release, a patch suffix is added.

In this approach, all numbers are clear for the team, and they do not tell the clients anything. But usually, users are not interested in the version in web applications.

Release Flow

Nowadays, there are many workflows: Git flow, GitHub flow, GitLab flow, Trunk-based development, etc.

Let’s go through the factors considered to choose which one to use.

Application size

If a small team develops the application, Git flow may be an unnecessary overhead. Creating these feature branches is time-consuming and makes more sense for monolith applications developed by a few teams. For microservices, it is much easier to use a trunk-based approach.

Release cycle and testing

Different applications have different release cycles. Web applications can be released multiple times per day.

For on-premise products, the opposite is true. Users don’t want to update the product too often because it is always a big deal. Therefore, such products usually go through additional testing cycles when the release is built. And it implies cherry-picking commits with fixes based on the results of testing.

Number of supported baselines

If you are developing a web application, only the latest version is usually sufficient.

On the contrary, when developing a library, or for example, a database, it is necessary to support several previous versions. This forces us to keep several baselines in the project and come up with a way for backporting new fixes to all baselines.

Branches vs Tags

There are two approaches to fixate a release. You can create the version number tag on the commit or cut off the release branch from master (code freezing).

Both approaches are valid and are used across different types of products.
In general, the tagging approach is better due to immutability, which reduces the chance of mistakes.
In the case of on-premise products or multiple baselines, release branches make more sense for the convenience of backports.

Conclusion

There are quite a few versioning options, and each has its use case. Therefore, you should not blindly use Semantic Versioning as the most popular one. Perhaps in your specific project, other approaches will be better suited and more understandable for developers or end-users.

--

--