Semantic Versioning
Method
A convention that splits a version number into three parts, so which part increased tells you what kind of change it was.
Why it exists
Using code someone else wrote means making a judgment every time they release. Can this be upgraded, and will upgrading break our code? A version number that only conveys order can't support that judgment. Whether 2.3 to 2.4 was a typo fix or a renamed function isn't visible in the number, so every upgrade becomes a small investigation.
Pagedeck was in that position. Theo bumped an outside library used by the document editor and pasting stopped working. One digit had moved and the notes said "improvements." What had actually happened was a function being removed. Finding the cause took half a day, and after that Theo stopped upgrading anything without checking. Safe, and it drifted toward not upgrading at all, which carries its own bill in unpatched security fixes.
Semantic versioning makes the number itself the input to that judgment. Looking at which part increased settles whether you have to check or can simply upgrade.
How to run it
The version is written as three parts separated by dots, and which part increases follows the nature of the change. In 2.4.1, the major is 2, the minor is 4, and the patch is 1.
- Increase the patch — a fix and nothing else. A bug was corrected and the way to use it is unchanged: 2.4.1 becomes 2.4.2. Consumers can upgrade without checking. Even so, code written to depend on that bug can break.
- Increase the minor — a capability was added. A new function or option exists while existing usage still works: 2.4.2 becomes 2.5.0. The patch resets to 0, which is part of the convention rather than a detail.
- Increase the major — existing usage breaks. A function is gone, or the shape of a value being passed changed: 2.5.0 becomes 3.0.0 and both lower parts reset. Consumers have to change their own code, which is why this is the part nobody increases casually.
- Before a first release — the rules are loose while the major is 0. The convention is that anything can break in 0.x, which is why 0.x code used in production gets pinned to a fixed version and upgraded deliberately.
- Marking and announcing — publish a list of what changed along with the part you increased. If the major moved, include the migration path. Bump the number without the list and consumers end up reading the code themselves. The point a number attaches to gets marked in a tool like Git, which manages change history in a distributed way, so that version's code can be pulled back out later.
Consumers use the convention to declare an allowed range. Pinning the major while letting the two lower parts move automatically is the most common setting. Fixes and additions then arrive on their own, and breaking changes arrive only when a person decides. That setting is only safe with continuous integration in place — merging often and verifying automatically.
When it fits and when it doesn't
It suits code other people consume: libraries, published integration contracts, internal services other teams call. When the makers and the users are different people with no conversation between them, the number carries the conversation, and it's the only channel that reaches every consumer.
Four limits.
- Whether a change breaks things is a contested judgment. What the maker sees as tidying is a break for the consumer — an error message reworded while someone had written a condition against that wording. Without erring toward caution here, the convention exists without earning trust, which is why ambiguous cases lean toward the major.
- It fits products end users use directly far less well. Nobody picks a version of a web service, so increasing a major has no meaning. Products like that use dates as numbers or don't publish numbers at all, since there is nothing for a consumer to decide.
- Frequent major increases dilute the signal. Code whose major moves three times in six months gets abandoned by consumers rather than followed. Collecting breaking changes and releasing them together works better, even though it means holding them longer.
- The number says nothing about quality. 1.0.0 doesn't mean finished and 5.0.0 doesn't mean more mature. The three parts convey only the nature of a change, which is less than people read into them.
Following the convention rests on people. So many teams write down the criteria for choosing which part to increase, and arrange that no one decides a major increase alone. The criteria matter more than the judgment of any one release.
How it sounds at work
"This one needs a major bump. We're removing a function."
Existing usage breaks, so the major moves.
"Only the minor moved, so we can just upgrade."
Reading the number and skipping the check.
"If we're using a 0.x in production, let's pin the version."
The pre-release range plays by looser rules.
Pagedeck applied the convention to an internal service other teams call. Theo wrote the criteria for choosing a part onto one page, and added a procedure of notifying the other teams two weeks before any major increase.
Breakage from upgrades dropped after that. What got harder was deciding on a major increase. Needing a two-week notice meant collecting the changes they wanted to make, and it settled into one large version every six months, announced well in advance. Easier for consumers, and it left the cost of holding a cleanup for six months.
What people get wrong
The most common belief is that the number describes maturity — that 1.0 means finished and bigger is better. But in this convention the major is closer to a count of how often something was broken. Code that broke often has a large number. Read as maturity, teams become reluctant to move the major, and reluctant teams hide breaking changes in a minor. At that moment the number stops carrying any information at all.
The other common belief is that a patch bump is always safe. The convention says so, which is why. But people are the ones following it, and a breaking change sometimes rides out in a patch by mistake. So even with automatic upgrades configured, the tests have to run alongside. Trusting the number and skipping verification are different things, and the second one is what gets teams burned.
Easily confused with
| Term | What it is | How it differs |
|---|---|---|
| Breaking change | A change that breaks existing users' code | The change itself, where semantic versioning is the convention that announces it through a number. Code that doesn't follow the convention still produces breaking changes. The only difference is whether consumers can know in advance |
Where to go next
- Version control
see which system this convention belongs to
- Git
see the tool that records the point a number gets attached to
Last updated 2026-09-16