The breaking change that does not say its name
Nobody breaks an API contract on purpose. You break it believing you are making a harmless change. The list of silent breaking changes, and the automated check that stops them.
Spectacular breaking changes, removing an endpoint, renaming a field, are in fact the least dangerous: everyone knows they break, they go through a major version, consumers are warned.
The real outages come from elsewhere: from changes their author believed harmless. First the rule that separates them from genuine minor changes, then the inventory, built up incident after incident.
The dividing line
A single rule separates the harmless from the dangerous, and it comes in two symmetrical questions. In the request, anything that restricts breaks: one more mandatory field, a tightened validation, an enumeration value removed. In the response, anything that removes or modifies breaks: a field deleted, a type changed, a widened enumeration the consumer cannot interpret.
Hence the answer to the most frequent question in a contract review. Adding an optional field in the request or a field in the response is not a breaking change, on one condition: that consumers ignore what they do not know. That condition is false more often than people think, because a client generated from the contract, or one that validates the response strictly, rejects an unexpected field. An API aimed at generated clients must therefore treat an addition in the response as an announced minor change, not as a non-event.
The breaking changes that do not look like one
Tightening a validation. The field accepted 100 characters, it now accepts 50, "to tidy things up". Every consumer that was sending 60 characters gets 400s. Any tightened validation is a breaking change, even when the old tolerance was an accident.
Fixing a spelling mistake in an enumeration. status: "recieved" becomes
"received". The spelling fix is a breaking change for every consumer that was comparing
the value.
Changing a default. Sorting moves from "date ascending" to "date descending", pagination from 100 to 20 items. No schema changes, every client that relied on the implicit behaviour behaves differently. Defaults are part of the contract.
Reordering the JSON, or changing a type. An integer that becomes a string ("id": 42 then
"id": "42"), a null field that disappears instead of being null: depending on the
parsers on the other side, it is invisible or fatal. You do not choose your consumers'
parsers.
Improving latency. An API that answered in 800 ms drops to 80 ms, and a consumer falls over, because its own race condition was masked by the slowness. Rare, real, and out of reach of any schema diff.
Tightening a quota or a timeout on the gateway. The breaking change can come from mediation itself: the platform configuration is part of the contract the consumer lives with, even if it appears in no OpenAPI file.
The real contract of an API is therefore not its OpenAPI file, it is its observable behaviour, defaults and tolerances included. Human review of a specification diff is not enough: half the breaking changes above do not appear in it.
The three automated checks, from cheapest to most complete
1. The contract diff in the pipeline. Compare every new version of the contract with
the previous one and refuse incompatible changes.
oasdiff does it for OpenAPI and classifies each
difference as a breaking change or not, with an exit code usable in continuous
integration. For Protobuf APIs, buf breaking fills the same role and does it better,
because the grammar lends itself to it. These tools catch the first four entries of the
inventory above, and neither of the last two.
2. Consumer-driven contract tests. Each consumer publishes what it actually uses, the provider replays those expectations on every build. Pact is the reference tooling, and its value is not technical: you are no longer told that "something has changed", but that "the payments team is going to break". Moving from an anonymous diff to a named impact changes the conversations. The real cost is organisational, since every consumer has to publish and maintain its expectations.
3. Traffic mirroring. Replay a sample of production traffic against the candidate version and compare the responses. It is the only net that catches behavioural breaking changes absent from the schema, defaults and tolerances included. More expensive, to be kept for APIs whose consumers are many or unknown.
Where to place the check, and how to waive it
The diff blocks at the merge request, not at deployment. A check that fails at delivery time is a check that gets disabled: the author discovers the problem when there is no time left to deal with it, and the first unofficial waiver becomes the custom.
So plan the waiver before you have to grant one. The form that holds is an explicit mention in the merge request, signed by name, with the list of consumers warned. It asks nobody's permission and leaves a trace: that is what makes it usable on a Friday evening, and checkable on the Monday.
When the breaking change is owned
Sometimes you have to break the contract. The subject then becomes the window left to consumers, and it gets signalled in the protocol rather than in an email.
Two standardised headers exist for this.
Deprecation, standardised in March 2025,
carries the date on which the resource is or will be deprecated.
Sunset carries the date on which it will
stop answering, never earlier than the first. Both are readable by a machine, which makes
it possible to measure how many consumers still call a doomed resource, and how fast that
number falls.
It is the only indicator that says whether the deprecation is moving. The window rule itself, depending on the nature of the consumer, and the versioning mechanics that go with it are covered in governance.
The cost of not having it
Without automation, every silent breaking change is discovered in production, on the consumer's side, with a blind diagnosis: their team looks for the cause in its own code, since "the API has not changed version". Count the hours on both sides, multiply by the release frequency, and the contract diff in the pipeline is probably the highest-return investment in your whole APIOps chain.
Published in June 2025.
On the same subject