A timeout change can turn a library upgrade into a production outage without changing a single function signature. If a request helper starts failing after five seconds instead of waiting for a response, consumers may see new errors across every service that upgrades.

A public API is more than its function signatures

When maintainers call a change “breaking,” they often start by checking whether a function was removed, renamed, or given a different parameter. That is necessary, but it misses changes to observable behavior. A documented default, error condition, ordering guarantee, or timeout can be part of the contract even when every method still compiles.

There is a second category: behavior that users relied on but the library never promised. A defect fix may deliberately stop that behavior. Under a strict compatibility reading, correcting an implementation bug can be a patch. In practice, the change can still break a workflow that has depended on the bug for years.

This is why a release decision needs two questions, not one: does the change break the stated contract, and how will existing users experience it? The first determines what SemVer normally signals. The second helps a maintainer decide whether that signal is adequate for the audience.

What SemVer signals—and what it does not

Semantic Versioning uses the order MAJOR.MINOR.PATCH. For a library that has declared a public API and is at version 1.0.0 or later, its central promise is straightforward: increment the major version for incompatible public-API changes, the minor version for backward-compatible functionality, and the patch version for backward-compatible bug fixes. A user can use those numbers to judge upgrade risk.

That promise is useful precisely because it is a communication rule, not a score for how important a change feels to the maintainer. A one-line removal can require a major version; a substantial internal rewrite may not require any version change if the public contract stays compatible.

But a version number cannot tell a consumer whether a particular incompatibility will affect their application, whether there is a workaround, or how severe the failure will be. SemVer communicates the compatibility category. Release notes, migration guidance, tests, and support policy must communicate the practical consequences.

The specification allows judgment for a real-world reason

The SemVer 2.0.0 specification includes a noteworthy qualification for bug fixes: if changing behavior back to what the public API intended would drastically affect a huge audience, a maintainer may choose a major release even when the fix could strictly be treated as a patch. Its advice is to use best judgment.

That is not a loophole saying that every surprising fix deserves a major number. It recognizes that compatibility is also about the expectations a version communicates. If users have built around an established behavior, shipping its reversal as an ordinary patch can make a patch update behave very differently from what they reasonably expect.

The distinction matters: the specification gives a compatibility framework and explicitly leaves room for judgment in this case; it does not prescribe a universal audience size or percentage at which a patch becomes a major. Maintainers must gather evidence about exposure and consequences, then choose a signal that gives affected users a fair chance to respond.

Use evidence to make “material impact” operational

Do not decide based only on how many downloads a package receives. Downloads can include repeated CI installs, unused transitive dependencies, and versions that never reach production. Instead, look for evidence of who exercises the changed behavior and what happens if it changes: downstream test failures, issue reports, documented usage, representative application tests, or opt-in release feedback.

Assess severity, concentration, detectability, and reversibility together. There is no universal percentage of affected users that makes a change major. A small group losing data may justify a stronger warning than a large group seeing a harmless formatting difference; a failure that is easy to detect and roll back is different from silent corruption that persists after downgrade.

Signal Evidence to check What it suggests
Severity Does the change cause failed requests, data loss, security exposure, or only a visible but harmless difference? More severe consequences raise the case for a major signal.
Concentration Do downstream tests, issue reports, or representative users show that a meaningful workflow depends on the old behavior? Affected installations concentrated in production-critical uses matter more than raw download counts.
Detectability Will users get a clear error, or can the change silently produce wrong results? Hard-to-detect harm calls for stronger warning and a safer rollout.
Reversibility Can users pin the old version, disable the new behavior, or restore affected data? Easy rollback supports a lower-risk path; irreversible effects support a major release.

Apply the rule to the five-second timeout

Suppose version 1 of a request library waits for a response unless the caller configures a timeout. A proposed release changes the default to five seconds and throws a timeout error after that limit. The immediate consequence is not just a new exception: a request that previously completed may now fail, and the application may abandon a job or return an error to its own user.

Assume the maintainer has only a small sample of downstream projects, and the sample does not establish whether five-second requests are rare, whether they carry critical work, or whether callers can safely retry. That evidence is not enough for a firm patch-versus-major decision. Guessing that “most users will be fine” would turn missing information into an implicit compatibility promise.

Use a staged test. Publish an opt-in timeout setting or a prerelease such as 2.0.0-rc.1, then ask representative downstream users to test the new default against long-running requests and production-like workflows. Record whether failures are visible, recoverable, and safely retryable.

If that test finds routine production requests exceeding five seconds, with consequential failures and no straightforward opt-out or safe retry, ship the default change in a major version. If the old behavior is not a documented contract, affected uses are exceptional, and users can configure the timeout or roll back without lasting harm, a patch may be defensible—but document the behavior correction explicitly.

A major version has costs beyond the version number

A major release gives users a clearer warning, but it also creates work. In npm, a consumer depending on ^1.4.0 does not automatically move to 2.0.0. That protects applications from silently taking the breaking change, while leaving teams to plan an upgrade, read migration notes, and test the new version.

For maintainers, the less visible cost is what users infer about support. If the project continues fixing security or critical defects on version 1 while version 2 becomes current, that policy needs engineering time and an explicit end point. If the project does not support old major lines, say so; a major number alone does not promise a long support window.

There is also a cost to using a major release for every uncomfortable change: users may learn to treat major numbers as routine and delay upgrades indefinitely. Avoid that by reserving the signal for genuine incompatibilities or unusually high-impact behavior corrections, and by making the migration path proportional to the disruption.

Make the warning useful with release notes and migration steps

A version number is a compressed message. Pair it with a short explanation that names the behavior, who is likely affected, and how to check. “Timeouts now default to five seconds” is more useful than “improved request handling,” because a consumer can search their own configuration and tests for the changed condition.

For a breaking change, include the old behavior, the new behavior, and a migration example. For instance: “Requests now time out after five seconds by default. Set timeout: 0 to retain no timeout, or choose an explicit duration.” Only publish such a workaround if the library actually supports it; otherwise, state what users need to change rather than inventing a configuration option.

Release automation can make the signal consistent without making the judgment. Tools such as semantic-release can derive a version, generate notes, and publish from commit conventions; its documentation uses a BREAKING CHANGE: footer to identify incompatible changes. Automation can enforce the decision a team encoded, but it cannot tell whether a timeout failure is material to downstream users.

Choose the release path, not just the number

Once the evidence is in, choose a release path that matches both the compatibility claim and the risk. The following sequence keeps the decision tied to observable facts rather than the size of the code diff.

  1. Write down the contract. Identify whether the old behavior is documented, tested as public behavior, or merely an implementation detail.
  2. Map exposure. Check downstream tests, reported use cases, and representative consumers to see which workflows depend on it.
  3. Rate the consequence. Describe the failure users would see, how they would detect it, and whether rollback or mitigation is practical.
  4. Choose the signal. Use a major release for an incompatible contract change, or when a behavior correction would materially surprise a large audience; use a patch only when the change is backward-compatible or the evidence supports treating it as a low-risk correction.
  5. Publish the evidence and escape hatch. Add migration notes, a test or prerelease when uncertainty remains, and a clear support policy for older versions.

What to do this week

Pick one proposed change in your library’s next release and create a one-page decision record. Include the old and new behavior, the evidence you have about downstream use, the most serious plausible failure, and whether users can detect and reverse it. If you cannot answer those questions, do not convert uncertainty into a patch release by default.

For uncertain changes, recruit a few representative consumers and run an opt-in test or prerelease. Decide in advance what finding changes the version choice: for the timeout example, routine production requests failing at five seconds without a safe configuration or recovery path should trigger a major release. If the test finds only rare, visible, reversible failures, document that evidence and make the lower-risk choice explicit.

SemVer supplies the vocabulary; maintainers choose how loudly to use it. The practical test is whether the version and release notes give the people most likely to be affected enough warning to protect their systems.