Skip to content

What is Semantic Versioning?

DevOps & Reliability, explained by the engineers who build it. Definition, how it works, use cases and common questions.

Semantic Versioning definition

Semantic versioning (SemVer) is a convention for numbering software releases as MAJOR.MINOR.PATCH, where each part signals the kind of change. A major increment means breaking changes, a minor increment adds backward-compatible features and a patch fixes bugs without changing behavior. It lets developers and package managers judge upgrade risk at a glance.

How MAJOR.MINOR.PATCH works

Take a library at version 2.4.1. Fixing a bug without changing its public interface produces 2.4.2. Adding a new, optional function produces 2.5.0, with the patch number reset. Removing a function, renaming a parameter or changing a default behavior that existing code relies on produces 3.0.0. The rules apply to the public API, so the first step in using SemVer is being clear about what that API is.

Versions below 1.0.0 are a special case: anything may change at any time, which is why young projects often stay on 0.x while their interface settles. Pre-release labels such as 2.0.0-beta.1 and build metadata such as 2.0.0+build.45 extend the format, and tags in version control, such as v2.4.1 in Git, mark the exact commit behind each release.

Version ranges in package managers

Package managers use SemVer to decide which updates are safe to install automatically. In npm, a caret range such as ^2.4.1 accepts any 2.x.x version at or above 2.4.1, trusting that minor and patch releases are compatible, while a tilde range such as ~2.4.1 accepts only patch updates. Lock files such as package-lock.json or pnpm-lock.yaml then pin exact versions, so every developer and CI build installs the same dependency tree.

Tools like Dependabot and Renovate read these ranges to open update pull requests, often grouping patch updates and flagging major ones for review. Automated tests in a CI/CD pipeline are what make accepting frequent minor and patch upgrades safe in practice.

Versioning APIs and apps

Web APIs borrow the same idea. Breaking changes, such as removing a field or changing its type, get a new major version, often in the URL (/v2/orders) or a header, while additive changes ship without one. Running two major versions side by side for a deprecation period gives clients time to migrate. Designing REST APIs so new fields are optional keeps most changes non-breaking.

Mobile apps also carry version and build numbers in the App Store and Google Play, but users rarely treat them as a compatibility signal. For apps, the critical versioning is on the backend API, because old app versions stay installed for months and must keep working.

Common SemVer mistakes

SemVer only works when maintainers follow it honestly and consumers understand its limits. Most version-related breakages trace back to one of these mistakes rather than to the scheme itself, and all of them are avoidable.

A useful habit is to write the changelog entry before the code is merged. If the entry has to tell callers they must now do something differently, the release is a major version, whatever the size of the diff. The common mistakes are:

  • Shipping breaking changes in a minor or patch release because the change seemed small
  • Treating a 0.x library as stable and accepting every update automatically
  • Forgetting that behavior changes, not just signature changes, can break callers
  • Never releasing 1.0.0, leaving users unsure what is stable
  • Skipping changelogs; Conventional Commits and semantic-release can generate them and choose the next version automatically

Semantic Versioning: common questions

Something else on your mind? Ask a consultant and get a reply within one business day.

What does a major version change mean?

A major version change, such as 2.x to 3.0.0, signals that the release contains breaking changes. Code that worked with the previous major version may need updates, so read the migration guide and changelog before upgrading, and upgrade major versions deliberately rather than automatically in a routine dependency bump.

What is the difference between caret and tilde in package.json?

A caret range like ^1.4.2 allows any version up to, but not including, 2.0.0, so it accepts new minor and patch releases. A tilde range like ~1.4.2 allows only patch releases below 1.5.0. Caret is npm's default; tilde is the more conservative choice for sensitive dependencies.

Should every project use semantic versioning?

Libraries, SDKs, APIs and anything other code depends on benefit most, because consumers need to judge upgrade risk. For end-user applications and websites deployed continuously, a date-based or build-number scheme is often simpler, since nobody installs them as a dependency and every release simply replaces the last.

Keep exploring the devops & reliability glossary

Need Semantic Versioning in your product?

A solutions consultant replies within one business day with next steps, a rough estimate and a suggested team.