How to track breaking changes in your npm dependencies
A dependency's breaking change rarely announces itself in your terminal. It shows up as a failed build after an upgrade nobody read up on. Here's how to see major versions coming, keep them out of routine updates, and find the changelog entries that tell you what to change.
Updated 6 min readBreaking changes, deprecations and versioning
The short answer
npm outdatedshows Wanted (the newest version your semver range allows) next to Latest (the version taggedlatest). A different major number between them means a breaking change is waiting.- npm saves dependencies with a caret by default:
^1.2.3accepts any 1.x from 1.2.3 up, never 2.0.0. For 0.x packages,^0.2.3stays below 0.3.0. - Let Renovate or Dependabot raise major updates separately from minor and patch ones (Renovate does this by default), and read the release notes in the pull request before merging.
- Watch the repositories you depend on most for releases only, and treat deprecation warnings as advance notice.
- Before a major upgrade, read every changelog entry between your version and the target, not just the newest one.
A breaking-change check you can run every week
Replace some-package with the dependency you're about to upgrade.
# What's behind? Wanted = newest your range allows, Latest = the "latest" tag
npm outdated
# Preview patch and minor updates only (no majors), then apply them
npx npm-check-updates --target minor
npx npm-check-updates --target minor -u && npm install
# Before a major upgrade: every version, and when each was published
npm view some-package versions
npm view some-package time
# Where its changelog lives
npm view some-package repository.urlnpm-check-updates edits package.json only; npm install then installs the new versions.
Free tool · no sign-up
Check that your breaking changes come through
Paste a GitHub release or CHANGELOG.md link and see which breaking changes, migration steps and deprecations a coding agent would actually find, as JSON plus an llms.txt summary.
No AI and nothing stored. Or paste a CHANGELOG.md instead
01Read npm outdated the right way
npm outdated lists every dependency with a newer version. The two columns that matter: “wanted is the maximum version of the package that satisfies the semver range specified in package.json”, and “latest is the version of the package tagged as latest in the registry.”
Package Current Wanted Latest Location Depended by
some-parser 1.8.2 1.9.0 2.1.0 node_modules/some-parser my-app
some-logger 3.2.0 3.2.4 3.2.4 node_modules/some-logger my-app- Current → Wanted is what
npm updatewould install within your range. If the package follows Semantic Versioning, that's features and fixes only. - Wanted → Latest across a major number (1.9.0 → 2.1.0 above) is where the breaking changes are. Semantic Versioning reserves the major version for “incompatible API changes”.
latestis a tag the maintainer moves; npm notes it “may or may not be the maximum version of the package, or the most-recently published version”.
02Know what your ranges let in
When you npm install a package, npm saves it with the save-prefix, which defaults to ^. Here's what the common ranges allow, from the node-semver docs:
| Range in package.json | Installs | Can a breaking change slip in? |
|---|---|---|
^1.2.3 | ≥ 1.2.3 and < 2.0.0 | Only if the maintainer breaks SemVer |
^0.2.3 | ≥ 0.2.3 and < 0.3.0 | Yes, more easily: in 0.y.z “anything MAY change at any time” |
^0.0.3 | ≥ 0.0.3 and < 0.0.4 | No: effectively pinned |
~1.2.3 | ≥ 1.2.3 and < 1.3.0 | Only if a patch release breaks something |
node-semver writes the upper bounds as <2.0.0-0 and so on, so prereleases of the next major are excluded too. Commit package-lock.json; npm says it's “intended to be committed into source repositories”, so a range never changes what CI installs without a pull request. More on version numbers in Semantic Versioning and changelogs.
03Keep major updates out of routine pull requests
Dependency bots are the best early warning, if majors arrive on their own. Renovate already does this: separateMajorMinor defaults to true, creating “a separate branch/PR if both minor and major version updates exist”, and fetchChangeLogs defaults to fetching changelogs and release notes into the pull request. To make every major wait for an explicit yes on its Dependency Dashboard:
{
"packageRules": [
{
"matchUpdateTypes": ["major"],
"dependencyDashboardApproval": true
}
]
}With Dependabot, group minor and patch updates so each major stands alone as its own pull request:
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
groups:
non-major:
update-types: ["minor", "patch"]Dependabot can also ignore majors with update-types: ["version-update:semver-major"], but then nothing tells you they exist. Separate pull requests are a better default than silence.
04Get told before the release lands
- Watch releases. On a dependency's GitHub repository, choose Watch → Custom and pick releases. You'll hear about new versions without the issue and pull request noise.
- Read deprecation warnings.
npm deprecatemakes npm show “a deprecation warning to all who attempt to install it”; a deprecated version or package is often the first sign of a removal. - Trace runtime deprecations. Run your tests with
node --trace-deprecationto print a stack trace for each deprecation warning, so you know which code to change. - Notice editor hints. APIs marked
@deprecatedin JSDoc or TypeScript are “typically displayed in a strike-through style” in editors like VS Code.
05Read the changelog between your version and the target
Going from 1.8.2 to 2.1.0 means reading 1.9.0, 2.0.0, 2.0.1 and 2.1.0, because a deprecation in 1.9 can become a removal in 2.0. Find the changelog with npm view some-package repository.url, then look for, in order: breaking changes, Removed, Deprecated, and any minimum Node.js or peer-dependency change.
Large projects publish a migration guide per major, such as Vite's. For libraries that host their changelog on LogPulse, an upgrade page lists every breaking change and migration step between any two versions, like this example from 1.4.0 to 2.0.0. For anything else, paste the releases page into the free converter to get the breaking changes of each version in one list.
06Let coding agents do the reading
Coding agents are good at mechanical migrations, if they know what changed. Give the agent the dependency's breaking changes and migration steps for the exact version range, not a vague “upgrade to latest”. A structured changelog makes that possible; changelogs for AI coding agents explains the format, and maintainers can see the other side in how to document breaking changes.
Before and after
Too vague
chore: bump all dependencies to latest
Specific and actionable
Upgrade some-parser 1.9.0 → 2.1.0. 2.0.0 removed parseLegacy(): replaced 3 call sites with parse(). 2.0.0 requires Node.js 20; CI already runs 22.
Fictional example: use your own verified names, versions and behavior.
LogPulse
Generate release notes with LogPulse
LogPulse is a hosted changelog that people and coding agents can both read. Here's exactly what it can do for the steps above, and what it can't.
Check your changelog, free
Paste a CHANGELOG.md or a GitHub releases link. A deterministic parser (no AI, nothing stored) shows the versions, breaking changes, migration steps and deprecations an agent can extract.
Draft notes from GitHub
Connect a repository: merged pull requests, commits to your default branch and published GitHub releases collect in an inbox. AI drafts a note in the tone you pick, listing breaking changes and deprecations only when the changes clearly show them. Nothing is published until you approve it. 3 AI drafts on Free; unlimited on Open source and Pro. Pro opens soon: .
Publish once, read everywhere
Approved notes go to a hosted changelog and an in-app widget, to email subscribers on Open source and Pro (Pro opens soon), and to a JSON feed and MCP server coding agents can query. CI and agents can publish with an API key.
What it doesn't do: LogPulse doesn't tag releases, bump versions, publish to npm or PyPI, or write CHANGELOG.md back to your repository; keep your release tooling for those. AI drafts can miss context, so review them like a pull request.
Before you publish
- npm outdated reviewed, and every Wanted → Latest major noted
- Minor and patch updates grouped; each major in its own pull request
- Every changelog entry between the current and target version read
- Deprecation warnings from npm, Node.js and the editor handled
- package-lock.json committed, and CI runs on the upgraded lockfile
- The upgrade commit says which breaking changes it addressed
Common questions
How do I know if an npm update has breaking changes?
Compare the major version: for packages that follow Semantic Versioning, a new major (1.x → 2.0.0) signals incompatible changes. Then confirm in the changelog or GitHub releases for every version in between. For 0.x packages, treat each minor version as potentially breaking.
Does a caret range protect me from breaking changes?
Mostly. ^1.2.3 never installs 2.0.0, but it does install any 1.x, so it relies on the maintainer following SemVer. A committed package-lock.json means nothing changes until a pull request updates it.
What's the difference between Wanted and Latest in npm outdated?
Wanted is the newest version your package.json range allows; Latest is whatever the package's latest tag points to. If they differ by a major version, upgrading to Latest means changing your range and reading the breaking changes.
Should I ignore major updates in Dependabot?
Usually not. Ignoring them hides upgrades you'll eventually need, and old majors eventually stop getting fixes. Group minor and patch updates instead, so each major arrives as its own reviewable pull request.
Sources
- npm Docs: npm outdated
- node-semver: ranges
- npm Docs: config (save-prefix)
- npm Docs: npm view
- npm Docs: npm deprecate
- npm Docs: package-lock.json
- npm-check-updates
- Renovate configuration options
- Dependabot options reference
- GitHub Docs: configuring notifications
- Node.js CLI options
- Semantic Versioning 2.0.0
Read next
How to keep a changelog for an npm package
Where npm users look for changes, how to keep versions, git tags and headings in sync, ship prereleases without moving latest, and deprecate old versions.
Read the guide Breaking changes, deprecations and versioningHow to document breaking changes
Write breaking changes people can migrate from: who is affected, old and new usage, deployment order, rollback limits and a test that proves the upgrade worked.
Read the guide Breaking changes, deprecations and versioningSemantic versioning cheat sheet for changelogs
Which change needs a major, minor or patch bump? A cheat sheet of 12 common changes with the changelog line for each, plus 0.x and prerelease rules.
Read the guide Breaking changes, deprecations and versioningChangelogs for AI coding agents
Help coding agents upgrade your library correctly: real versions, explicit breaking changes and deprecations, and a machine-readable JSON feed or MCP server.
Read the guideMore guides: breaking changes, deprecations and versioning
All release notes guidesTools and resources
LogPulse
Changelogs coding agents can upgrade from.
Publish versions, breaking changes, migration steps and deprecations once. People get a widget and hosted changelog; agents get a JSON feed and MCP server. Free for open source.