Semantic Versioning (SemVer)
Status: Complete
Category: Delivery
Default enforcement: Soft
Author: PushBackLog team
Tags
- Topic: delivery, api-design, release-management
- Skillset: engineering, devops
- Technology: generic
- Stage: delivery, operations
Summary
Semantic Versioning (SemVer) is a versioning scheme in which a version number MAJOR.MINOR.PATCH communicates the nature of changes in each release: breaking changes increment MAJOR, backwards-compatible new features increment MINOR, and backwards-compatible bug fixes increment PATCH. SemVer creates a shared contract between package publishers and consumers: by reading a version number, a consumer can reason about the upgrade risk without reading a changelog. It is the standard for npm packages, most open-source libraries, and any API with external consumers.
Rationale
Version numbers are communication, not bookkeeping
Without a versioning convention, a version bump from 2.3.1 to 2.3.2 might be a bug fix, a new feature, or a breaking change — the consumer has no way to know without reading the full changelog. This makes automated dependency updates dangerous and slows teams down. SemVer transforms version numbers into a meaningful contract: the increment type signals what changed.
Automated tooling depends on SemVer semantics
Package managers (npm, cargo, pip), CI dependency update tools (Renovate, Dependabot), and changelogs generated from conventional commits all rely on SemVer semantics to make correct decisions. A ^1.0.0 range in package.json means “accept any 1.x.x” — that contract breaks if a 1.1.0 release contains a breaking change. Correct SemVer makes the whole dependency management ecosystem work correctly.
Guidance
The SemVer contract
MAJOR.MINOR.PATCH[-PRERELEASE][+BUILD]
│ │ │
│ │ └── Bug fix: backwards compatible
│ └──────── New feature: backwards compatible
└────────────── Breaking change: not backwards compatible
When to increment each segment:
| Change type | Increment | Example |
|---|---|---|
| Breaking API change | MAJOR | Remove a field, rename a method, change a type |
| New backwards-compatible feature | MINOR | Add a new endpoint, add an optional parameter |
| Bug fix | PATCH | Fix incorrect calculation, fix crash |
| Security fix (no API change) | PATCH | Upgrade vulnerable dependency |
The 0.x special case
While MAJOR is 0, the API is considered unstable:
0.MINOR.PATCH
0.xmeans any change can be breaking- Use
0.xduring initial development before making a public contract commitment - Once you increment to
1.0.0, you are committing to backwards compatibility
Pre-release versions
1.2.0-alpha.1 # Alpha — work in progress
1.2.0-beta.1 # Beta — feature complete, testing in progress
1.2.0-rc.1 # Release candidate — ready for final verification
Pre-release versions have lower precedence than the associated normal version: 1.2.0-alpha.1 < 1.2.0.
Conventional Commits → SemVer automation
Combined with Conventional Commits, version bumps can be automated:
| Commit type | SemVer bump |
|---|---|
fix: | PATCH |
feat: | MINOR |
feat!: or BREAKING CHANGE: footer | MAJOR |
refactor:, docs:, chore: | No bump |
Tools like semantic-release and release-please automatically compute the next version, generate a changelog, create a git tag, and publish to the package registry based on commit history.
# .github/workflows/release.yml
- name: Create Release
uses: google-github-actions/release-please-action@v4
with:
release-type: node
# Reads conventional commits since last release
# Computes correct SemVer bump
# Creates changelog PR automatically
npm version ranges
Understanding how SemVer ranges work in package.json:
| Range | Meaning | Example binds to |
|---|---|---|
^1.2.3 | Allow MINOR and PATCH bumps | >= 1.2.3 < 2.0.0 |
~1.2.3 | Allow PATCH bumps only | >= 1.2.3 < 1.3.0 |
1.2.3 | Exact version only | 1.2.3 |
>=1.2.3 <2.0.0 | Explicit range | As stated |
The most common source of breaking changes in Node.js projects is a transitive dependency making an incorrect version bump.
API versioning vs. SemVer
SemVer for HTTP APIs is distinct from package SemVer. HTTP API versioning (URI versioning, header versioning) is covered in API Versioning. SemVer applies to the API’s release version communicated to consumers, not necessarily the URL structure.
Review checklist
- All public packages use SemVer
- MAJOR is incremented for every breaking change
- Breaking changes are never sneaked into MINOR/PATCH releases
- Changelog documents changes per version
- Pre-release labels (
alpha,beta,rc) are used before public production releases -
semantic-releaseor equivalent automates version computation from commit history