The Value of SemVer
Hacker News recently had a discussion of a fairly popular Tweet on the meaning of SemVer.
Absolutely. The thing about semver major version numbers are that they don't mean new stuff, they're a permanent reminder of how many times you got the API wrong. Semver doesn't mean MAJOR.MINOR.PATCH, it means FAILS.FEATURES.BUGS
— Will McGugan (@willmcgugan) August 6, 2021
There is a lot of truth in Will McGugan’s tweet. As a software developer I understand and empathize with this take. It’s too inward-focused and I prefer a more customer-/user-focused alternative. SemVer gives users/customers an understanding of the upgrade’s risk. It’s about trust and what processes need to be in place to perform the upgrade. In theory I should be able to install a minor or a patch without any human intervention. My CI should even be able to run bundle update
or cargo update
, run tests and commit the updated dependencies. I cannot do this for major versions, since they include breaking changes. A human needs to get involved and likely needs to set at least some time aside. Trust in a major version update not breaking my app is zero by definition.
The difference between minors and patch versions gets fuzzier. The patch only includes bug fixes and the minor includes new features. Neither of them should include new bugs. In practice we make mistakes when we develop software. A patch has fewer code changes which means less opportunity to introduce bugs. Because of this you might want to use different processes for minor or patch upgrades. This might depend on things like
- what your application does
- the track record of the software/library you are upgrading
- complexity of piece of software you are upgrading
- maturity of your own upgrade processes
So I believe that most users/customers do or should think about SemVer versions like this:
MAJOR - Very likely to break for many users and we need to plan at least some time for this upgrade
MINOR - Should be fairly safe to upgrade
PATCH - As risk free as upgrades can get
My view on this might be skewed as I work on complex software that gets used by very large enterprise customers for mission-critical applications (example). I know that many businesses would prefer to get a patch that only contains the bug fixes that they directly want. This is a somewhat understandable outcome from extreme aversion of immediate risk. The same principle applies to any dependency upgrade on any software. Even if an issue in a library only leads to someone getting interrupted by a CI failure. It’s not comparable to a production outage of a fraud detection system, but it’s a nuisance. Especially when it happens at an inopportune time.
Thinking this risk-based reasoning of SemVer through we encounter some interesting edge cases. What about a harmless bug that requires a complex fix that touches a lot of code? Depending on what you build and who uses it, you might want to consider addressing bugs like this only in a minor. This is especially true if the changes are in the same area of the code base as some core functionality. Not getting users or customers a harmless bug fix isn’t great, but it sure beats losing their trust in releases.