DEV Community

WhatShipped
WhatShipped

Posted on

Semantic versioning explained - and why most projects get it wrong

"v2.0 is out!"

Does that mean you should upgrade immediately? Will it break your integration? What actually changed?

Semantic versioning (SemVer) was designed to answer these questions through the version number itself. Most projects use the number format without following the meaning — which defeats the whole point.


The spec in 30 seconds

SemVer is three numbers: MAJOR.MINOR.PATCH

2.4.1
│ │ └── PATCH: backward-compatible bug fixes
│ └──── MINOR: new features, backward compatible
└────── MAJOR: breaking changes
Enter fullscreen mode Exit fullscreen mode

If every project followed this consistently, the version number alone would tell you whether an upgrade is safe. That's the goal.


What each number means in practice

PATCH (1.0.0 → 1.0.1)
A bug was fixed. Existing behavior is the same or better. Safe to update without reading anything.

MINOR (1.0.0 → 1.1.0)
A new feature was added. Existing code continues to work exactly as before. Update if you want access to the new functionality; skip it if you don't.

MAJOR (1.0.0 → 2.0.0)
Something changed in a way that may break existing code. Read the changelog before upgrading. You may need to update your integration.

When a project follows this consistently, users develop accurate intuition about upgrades: patches are safe, minors are low-risk, majors require attention.


The most common mistake

Bumping MAJOR for anything that feels "big."

A complete internal rewrite that doesn't change the public API is still a MINOR bump. A major visual redesign of a library's output that doesn't change how you call it is still MINOR. A significant new feature set is still MINOR.

MAJOR is specifically for breaking changes — changes that will cause existing code using your package to fail or behave incorrectly without modification.

Your sense of how significant the work was doesn't determine the version. The impact on existing users does.


The 0.x convention

While your major version is 0 (0.y.z), you're sending a signal: this is pre-stable, the API may change at any time.

In 0.x, it's acceptable to make breaking changes in minor version bumps. The convention acknowledges that early-stage projects iterate on their API before committing to stability.

When should you move to 1.0? When you're prepared to maintain backward compatibility and follow the MAJOR/MINOR/PATCH contract. It doesn't mean the software is perfect — it means you're committing to a contract with your users.


SemVer and changelogs are a pair

SemVer answers: how risky is this upgrade?

A changelog answers: what specifically changed?

One without the other is incomplete. The version number gives users a risk signal. The changelog gives them the information to act on it. Together, they enable users to make fast, confident decisions about whether and when to upgrade.

A MAJOR bump with no changelog that explains what broke and how to migrate is as frustrating as a breaking change with no version bump at all.


The decision rule

If you're ever unsure which number to bump, there's a single question that resolves it:

"Does code that currently uses my library/tool still work after this change, without modification?"

  • Yes, and it's a bug fix → PATCH
  • Yes, and it's a new feature → MINOR
  • No → MAJOR

That's the whole decision. The spec is detailed, but the practical rule is this simple.


Making the release worth reading

Once you've decided on the version bump, the changelog is what makes the release useful. A formatted, scannable CHANGELOG.md that groups changes by type (Added, Fixed, Breaking) paired with a clear SemVer bump is the complete picture.

If writing that changelog is the friction that causes you to skip it, WhatShipped generates it from your git history. There's 1 free generation — enough to produce the changelog for your next release without any manual work.


Version numbers are a communication protocol between you and your users. When you use them correctly, you reduce confusion, reduce support overhead, and build trust. It's one of the lowest-effort, highest-signal things a maintainer can do.

Top comments (0)