Safeguard
Developer Tools•

What counts as a breaking change under semantic versioning?

Semver says a major bump signals backward incompatible public API changes. Learn what that covers, what it misses and how to test for it yourself.

Safeguard Security Team
4 min read

Under semantic versioning, a breaking change is any backward incompatible change to the public API, and it requires a major version bump. The catch is that the public API is whatever the author declares it to be. Behavior changes, defaults and security fixes can still break you inside a minor release.

What the specification says

The Semantic Versioning 2.0.0 text says the major version X, for X greater than zero, must be incremented if any backward incompatible changes are introduced to the public API. It may also include minor and patch level changes, and patch and minor are reset to zero. Minor versions add functionality in a backward compatible manner, and patch versions are for backward compatible bug fixes.

The spec also depends on an author declaring a public API. The promise only covers what has been declared.

Where reality differs

ChangeDeclared breaking?Can still break you
Removing or renaming a public functionYes, majorN/A
Changing a default valueDepends on the projectYes
Fixing a bug you relied onUsually patchYes
Tightening validation for securityOften minor or patchYes
Dropping an old runtime versionProject decidesYes
Changing error messages or orderingRarelyIf you parse them

Security fixes are the interesting row. A fix that rejects malformed input, changes a parser default or refuses an unsafe path is correct and may still break a caller who depended on the loose behavior. A project may ship it in a minor release because the declared API did not change.

Symfony's published backward compatibility promise is a good illustration of how seriously mature projects treat this. It says only major releases may break backward compatibility, minor releases must not break the existing API of that branch, and deprecation messages are provided to help migration across majors. It also admits that almost every change can potentially break an application, because even adding a method can clash with a subclass that defined the same method.

How to test for breakage yourself

  1. Read the changelog for every version you skip, not only the headline release. Look for words like default, now rejects, no longer and removed.
  2. Run your tests with deprecation warnings enabled before and after.
  3. Add tests for behavior you depend on that is not obviously in the public API: parsing, error handling, serialization, ordering.
  4. Compare outputs on real sample inputs between old and new versions.
  5. Deploy to a canary or staging environment that gets production shaped traffic.

Which upgrades deserve the most care

Rank by blast radius: libraries in the request path, authentication, serialization, and anything that handles untrusted input. A patch release of a logging helper deserves a quick look. A minor release of an HTTP framework or parser deserves a real test pass.

For these, read the diff of the security relevant files if you can. Semver tells you what the author intended, and tests tell you what happened.

Quick check

Can a minor release break my application?

Yes, if it changes behavior you depended on outside the declared public API, or if the author misjudged compatibility.

Does a major version bump always mean a hard upgrade?

No. It means breaking changes are permitted. Many majors affect only a small part of the API.

Safeguard shows which of your dependency updates carry known vulnerabilities, so you can spend test effort where the security payoff is. Try the free scan at gold.safeguard.sh/scan.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.