Jul 3, 2017 · 5 min read

An illustrated guide to semantic versioning


Semantic versioning does not reflect the size of the update, but the changes in the software’s public API.


Loose dependencies of software, matching to highest patch (~) or even highest minor (^), is very common, and spawning new images in different times could result in different version of modules on different machines. This is desired behaviour. We want the ability to run latest versions of modules with the latest performance improvements and vulnerability fixes, without the need to manually update the code.

Where applicable, we use semantic versioning to manage this. It is important to follow the rules of versioning to avoid breakage. Bad versioning can cause unexpected behaviour, from different bundle outputs causing different fingerprints across servers, to operations straight up breaking in a project we didn’t update. These instances can be the hardest to locate and debug, because they do not involve direct code change.

Enter Joe

Image for post
Image for post
Joe Shmoe 1.0.0

This is where we meet Joe, in Joe’s first major release. Joe is a software with internal logic and an API, making his functionality available to his consumers (He can walk, talk, and throw a fist).


Content: Internal fix
Example: Bug fix, Performance improvement, environment or internal tweaks
Policy: Consumers should update their software without hesitation

Image for post
Image for post
Joe Shmoe 1.0.1

We thought Joe’s a bit too slow on his feet. Research suggests sandals can really help Joe pick up the pace. This is an internal update, it does not change any of Joe’s behaviour or abilities, but improves on existing ones. We’ll update a patch so our consumers know they should update.


Content: Interface change with full backward compatibility
Example: New feature, Endpoint declared deprecated
Policy: Update your software to get some new features. Nothing will break

Image for post
Image for post
Joe Shmoe 1.1.0

As we go along adventuring with Joe, we decide to add some functionality to Joe’s interface. We’ve added some weaponry. Now Joe’s able to fight more fiercely and tackle more challenging endeavours.

Since we’ve added to Joe’s interface, we’re upgrading a minor version. Joe can do everything he used to, and then some!

Image for post
Image for post
Joe Shmoe 1.2.0

We’re continuing to upgrade Joe with new features, but our tests suggest Joe could perform better using an axe instead of his sword. Because we want Joe’s users to keep updating without fear of old functionality breaking, we’ve decided to give him a small axe with which he can still jab, but we’re recommending users to start swinging, instead. This is called a deprecation strategy.


Content: Interface change breaking backward compatibility
Example: Change API endpoint name or signature, Remove an endpoint
Policy: Test your system extensively post update.
Migration documents may be in order

Image for post
Image for post
Joe Shmoe 2.0.0

Finally, we decide it’s time to move on to Joe’s big boy’s axe. To do that we need to free up Joe’s other hand, which means he can’t use his shield any more. We’ve removed some of Joe’s functionality, which means this version is not fully backward compatible. It means users relying on Joe’s behaviour should update carefully, and replace instances where they’re on his shield if there are any. Their programs might break if they don’t test their usage. And while we’re breaking compatibility, we’re going to drop support of Jab, too.


Image for post
Image for post
Joe Shmoe 2.0.0

It has come to our attention, that a Joe has a vulnerability caused by his feather. It makes him too visible on the battle field and we’ve decided to remove it.
Because this is a patch, our users know they can safely upgrade without rigorously testing their programs.

Image for post
Image for post
Joe Shmoe 1.2.1

But the feather wasn’t introduced in this major release, it was introduced in an older version. If we want to keep supporting our user base, we should release a patch to our old versions as well.

This is where tagging comes in. You may have noticed, we’ve also published tags (named versions of our software), along the way and used our release numbers as tag names. Now we can easily go back and release a fix, then increment a patch on the old version.



$ git tag -a 1.0.0-alpha.1 -m "Testing the new interface"

Release candidate means this version is under consideration for release.

$ git tag -a 2.1.0-rc.3 -m "Still performing some tests, but pretty sure this is the interface we'll be using"

Build Number


Build versions do not have any precedence one over the other.

When *not* to update

Since these changes are only meant for other maintainers, or to instruct how to better use the program, they do not affect the program’s operations and should not trigger a version update (not including build number extension of course).


$ git tag -a 0.0.4 -m "removed half of the interface ¯\_(ツ)_/¯"


Image for post
Image for post

Fiverr Engineering

The technology behind the platform that’s disrupting the…

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store