In semantic versioning, what does each of the three number positions promise a consumer?
answer
- Three positions, three sizes of upgrade cost
- Ask what a consumer must change
- One suffix ranks lower, one is ignored
- A leading zero suspends the promise
basics
~20 sSemantic versioning reads a version as major.minor.patch: a major bump warns of an incompatible change, a minor bump adds capability without breaking callers, and a patch bump is a backwards-compatible fix. The number is a compatibility promise, not marketing.
solid answer
~50 sThe three positions tell a consumer how much work an upgrade will cost them. **Patch** means backwards-compatible fixes only, so a consumer can take it without reading anything. **Minor** means new capability was added and existing usage still works. **Major** means something a consumer depends on has changed or gone, and the upgrade needs their attention. Two suffixes qualify the number: a *pre-release* identifier marks a version as not yet final and ranks below the plain version, while *build metadata* is carried for identification and ignored when deciding which of two versions is newer. A leading zero major marks initial development, where the promise is explicitly not yet in force. The value of all this is entirely conventional — the moment a team ships a break in a patch, consumers stop reading the number and start pinning exact versions.
code
pseudocode · 6 lines1.4.2 fix only; a consumer upgrades without reading
1.5.0 an optional input was added; old calls unaffected
2.0.0 a documented field was removed; callers must change
2.1.0-rc.3 pre-release: ranks BELOW 2.1.0
2.1.0 the final release
2.1.0+build.5417 build metadata: ignored when ranking versionsgo deeper
Be ready to name the three positions in order and give one example of a change that belongs in each. Interviewers use this to check you read a version number as information rather than as a label someone increments.
Explain the mechanics: which positions reset, what the two suffixes do, and how you decide the position from the change rather than from the size of the diff. Expect to be asked where you would put a tightened validation rule.
Show the judgement of a publisher. Talk about how you catch an accidental break before it ships, what you do after one has escaped, and how a deprecation runs across a whole major line rather than a single release.
Own the organisational side: whether the number is trustworthy across every artefact you publish, who arbitrates a disputed bump, and what you accept when a major bump is expensive enough that teams start hiding breaks in minors.
## Three positions, one contract Semantic versioning is not a numbering scheme; it is a **contract expressed as a number**. Its whole purpose is to let a consumer decide, without reading a changelog and without running your test suite, how much of their own work an upgrade will cost. The three positions answer that in increasing order of expense: - **Patch** (the third position) — backwards-compatible bug fixes. Nothing a consumer relies on changes. This is the upgrade you can take automatically. - **Minor** (the second) — functionality was added, and everything that worked before still works. New surface appears; nothing disappears. - **Major** (the first) — an incompatible change. Something a consumer was entitled to use is gone, or behaves differently. The upgrade requires their attention. When a position increases, the positions to its right reset to zero: after 2.7.4 a minor release is 2.8.0, and a major release is 3.0.0. ## Reading a change into a position | The change you made | Position that moves | Why | |---|---|---| | Fixed wrong behaviour, same surface | Patch | Callers keep working, and were already broken by the bug | | Added an optional input or a new operation | Minor | Existing calls are untouched | | Marked something deprecated, still working | Minor | Nothing breaks yet; the warning is the feature | | Removed or renamed something public | Major | Working code stops working | | Tightened validation that previously passed | Major | Inputs that were accepted are now rejected | | Changed a default value callers depended on | Major | Behaviour changes without the caller changing | The last two rows are where teams argue. The test is not *how big the diff was* — it is **whether code that worked yesterday still works today**. A one-line change can be a major, and a ten-thousand-line rewrite that preserves every documented behaviour is a minor. ## Pre-release identifiers and build metadata Two suffixes exist and they do different jobs: 1. A **pre-release identifier** (appended after a hyphen, as in `2.1.0-rc.3`) marks a version as unfinished. It has **lower** precedence than the plain version it points at, so `2.1.0-rc.3` is older than `2.1.0`, and the compatibility promise is not yet in force for it. 2. **Build metadata** (appended after a plus sign, as in `2.1.0+build.5417`) identifies *which build* produced the artefact. It is **ignored** when comparing versions: two versions differing only in build metadata have the same precedence. The common error is treating build metadata as a tiebreaker. It is a label, not a rank. ## Zero as a major version A version whose major position is zero means **initial development**: the interface may change at any time, and the compatibility promise is explicitly suspended. Consumers of a zero-major dependency should pin an exact version rather than accept a range. Publishing 1.0.0 is therefore not a quality statement about the code — it is the moment a team commits to the contract, and it should be a deliberate decision rather than an accident of a version bump. ## How teams break the promise - **A breaking change shipped as a patch**, justified with "nobody uses that field". Nobody you can see. Patches are exactly the upgrades consumers take blind, which is why this is the most damaging of the four. - **A major bump for marketing**, because a release feels significant. This trains consumers to ignore the position that carries the strongest warning. - **Version numbers tracking the calendar or the iteration count** rather than compatibility. The number then carries no information an upgrade decision can use. - **Modifying the contents of an already published version.** Once published, a version must mean one thing forever; re-publishing under the same number is the same failure as moving a released name in history. ## What a consumer is entitled to assume Given `2.8.3`, a consumer may assume that everything documented at `2.0.0` still works, that anything added since is optional, and that moving to `2.9.0` will not require code changes. That entitlement is what allows a dependency to be declared as a range accepting any `2.x` release. It is also how a **deprecation window** is expressed. You do not delete in the release that announces the deprecation. The conventional sequence is: announce in a minor release while the old surface keeps working, keep it working for the remainder of that major line, and remove it only at the next major — stating, at announcement time, the earliest version in which the removal may appear. A consumer who upgrades minors promptly then never meets a surprise break; one who skips a major has been told, in the number itself, that work is waiting for them.
- A field consumers already read was removed and the change shipped as a patch. What should have happened?The removal is incompatible, so it belonged in a major release. The recovery is to restore the field immediately in a new patch, mark it deprecated in the next minor while it keeps working, and remove it only at the next major. Shipping the removal again under the same number is not an option: a published version must keep meaning one thing, so the correction always costs a new version number.
- How do you express a deprecation window through version numbers alone?Announce the deprecation in a minor release with the old surface fully working, say at that moment the earliest version in which removal may occur, keep it working for the rest of that major line, and remove it at the major bump. Consumers who track minors get warning without breakage, and consumers who cross a major know from the number that work is required.
- What does a leading zero in the major position change for a consumer?It suspends the compatibility promise: during initial development anything may change at any time, including in a minor bump. A consumer should pin an exact version rather than a range, and should expect to read release notes for every upgrade. Reaching 1.0.0 is the point at which the publisher accepts the contract, not a claim about code quality.
saying these in an interview costs you the question
- Bumps the major position for marketing or for a big feature launch
- Ships a breaking change as a patch because nobody seems to use it
- Treats build metadata as part of version ordering
- Thinks a minor bump may drop a documented behaviour
- Assumes a zero major carries the same compatibility promise
- Sizes the bump by how large the diff was