How to Detect Breaking Changes Before Your Release
A breaking change is cheap to catch during review and expensive to catch after release: users' integrations fail, support tickets arrive, and you spend a sprint on backports or migration posts. Detection works in layers — convention, automation, communication — and teams that ship clean releases run all three, not just the "we have tests" one.
What counts as a breaking change
Before tooling, agree on the definition, because it determines what you detect:
- API: removed endpoints or fields, renamed parameters, changed types or defaults, tightened validation.
- CLI and config: removed flags, renamed config keys, changed environment variables, new required settings.
- Data format: changed wire format, file format, or database schema the user migrates.
- Behavior: same call, different result — the sneakiest class, and the one tests catch better than static tools.
Layer 1: conventions and markers
This layer is free and catches more than you would expect, because it makes intent explicit at the point where the author knows it.
- Use the
BREAKING CHANGEfooter in conventional commits, or a!after the type (feat!:), so any tool that parses commits can find it. - Require a
breakinglabel on pull requests — it is the signal PR-based changelog tools read. - Enforce semver: a major bump is your public promise that the release contains breakage, and skipping it is itself a detectable error.
- Keep a deprecation policy (warn one or two releases before removal). Deprecation turns a surprise into a scheduled event.
Layer 2: automated detection
Conventions need enforcement, and this is where CI earns its keep:
- Semver gate. A release tagged without a major bump while
BREAKING CHANGEmarkers orbreakinglabels are present fails the build. This catches the "forgot to bump the version" class, which is common. - Diff heuristics. Compare the new tag against the previous one: removed exported symbols, changed signatures, dropped CLI flags. Language-specific tooling exists for APIs and schemas; even a required diff review of public interfaces on major PRs catches a lot.
- Contract tests. Snapshot the public API surface (endpoints, request and response shapes, CLI
--helpoutput) and assert on it in CI. When a PR changes the snapshot, the breaking change is visible on the PR, not on release day. - Deprecation tracker. A small list of deprecated items with removal versions; CI fails the release that removes something still scheduled for the future.
No single tool sees everything — behavior changes slip past every static check. That is why the layers stack: markers capture intent, heuristics capture structure, tests capture behavior.
Layer 3: make it visible to your users
Detection that stays in CI only protects your release process. The part that protects your users is communication:
- Flag breaking changes in the changelog entry itself — highlighted, at the top, with a migration note, not buried under "Fixed a typo."
- Put the breaking changes in the email digest subject or first line, so subscribers cannot miss them.
- For API users, link from the flag to a migration section with old-to-new examples.
A changelog that flags breaking changes does detection work for you on the reader side: many users read the changelog before upgrading, and a highlighted flag turns a post-failure support ticket into a pre-upgrade migration. This is one reason to generate the changelog from the same pipeline that tags the release, which our pull-request automation guide covers.
ShipChangelog
ShipChangelog covers the communication layer of this stack: major-version bumps and BREAKING CHANGE markers in your merged PRs are detected and highlighted in the generated entry, in all three audience versions, so the flag appears on the page, in RSS, and in the email digest. Breaking-change detection is part of the Pro plan at $12.99/month; the free tier covers one repo with 5 entries a month. The semver gate and contract tests remain your CI's job.
FAQ
Do I need a formal API-diffing tool?
It depends on your surface area. A small product can get most of the value from the semver gate, PR labels, and snapshotting the public interfaces in tests. Dedicated API-diff tooling pays off when the API is wide and changes are frequent.
What about behavior changes that look identical in the diff?
Those are the tests' job, not the tools' job. Contract tests plus a regression suite catch "same call, different result." Detection tooling is good at structure — removed things, renamed things, retyped things — and weaker at intent.
Is a major version bump enough communication?
No. A bump tells users something broke; it does not tell them what or how to fix it. The bump plus a highlighted changelog flag with a migration note is the complete unit.
ShipChangelog writes these changelogs for you — start free with 1 repo.