The 8 API changes that break production (and how to catch every one)
Most breaking changes aren't dramatic. They're one-line diffs. Someone renames a field. A parameter goes from optional to required. An endpoint gets removed during a cleanup pass. The caller never agreed to the change. By the time they find out, it's usually in production — a 400 from a field that no longer exists, a deserialization error on a type that changed underneath them. All 8 of the most common kinds follow the same pattern: invisible in code review, obvious in production.
The 8 kinds
1. required_param_added
Adding a required parameter forces every existing caller to update immediately. None of them will know until they hit a 400. The server starts rejecting requests that worked yesterday — because the new parameter has no default and the API won't proceed without it. Existing callers had no way to anticipate it. The breakage is total and immediate.
2. endpoint_removed
Deleting an endpoint with active consumers is the most immediate kind of breakage. Every client that calls that path gets a 404 where they used to get a 200. There is no graceful degradation. The operation they depended on simply no longer exists.
3. auth_changed
Changing the auth scheme silently invalidates every existing client token. A service that moved from API key to Bearer token breaks every client that still sends X-API-Key. The request reaches the server. The server rejects it. The caller sees a 401 with no indication that the auth scheme itself changed.
4. enum_value_removed
Callers pattern-match on enum values. Removing one breaks any code with a switch or match statement that handled it. In strongly typed languages, this surfaces at compile time if the client was regenerated — but most aren't. In dynamic languages, the unhandled case silently falls through or throws at runtime, often in a code path that's rarely exercised.
5. response_field_removed
If your clients depend on a field you removed, they find out in production when they try to read it. The response parses. The object looks valid. The field is just missing. In a typed client, you get a null where you expected a value. In a dynamic client, you get undefined. Either way the downstream logic breaks, and the error message doesn't point to the API change.
6. type_changed
Changing a field from string to integer passes code review. It doesn't pass production. Clients that stored, compared, or transmitted that field as a string now have a type mismatch on every operation that touches it. JSON parsers in many languages will coerce silently in one direction and throw in the other. The failure mode depends on the client's language and serialization library — which means it often surfaces differently across consumers.
7. optional_param_now_required
Flipping a previously optional parameter to required breaks callers that relied on the default. They were sending valid requests before — the parameter was optional, so they omitted it. Now the server rejects those requests. The callers have no idea the contract changed. From their perspective, valid requests started failing.
8. field_removed
Removing a body field from a request schema invalidates every payload that included it. Strict servers will reject the request. Lenient servers may silently drop the field and proceed with incomplete data. Neither outcome is what the caller expected. The field was documented. They relied on it. Now it's gone.
The common thread
None of these require a major version bump. All can slip through a standard code review if the reviewer doesn't know what existing callers depend on. The API change looks reasonable in isolation — cleaning up a field, tightening a parameter, simplifying the auth model. The breakage only becomes visible when you hold the change against what every consumer is actually sending and receiving. That context doesn't exist in a pull request. It exists in the spec history and the current call patterns, and most code review processes have no way to surface it.
What StateAnchor does
StateAnchor catches all 8 automatically on every push. The gate engine diffs your spec against the previous version, classifies every change against our 34-scenario ground-truth corpus, and makes a binary decision before anything reaches production. We validated 100% detection accuracy on all 8 breaking change kinds — every scenario in the corpus, every time. If a breaking change is in the diff, the gate blocks it. If it's not, it passes. No thresholds to tune, no scores to interpret. The verdict is categorical: ERR blocks, WARN flags, INFO passes.
Connect your repo, point StateAnchor at your spec, and every future push runs the gate automatically. The 8 kinds above become impossible to ship undetected.
See it in action — connect your repo and run the gate on your next push.
Get started free →All 34 gate kinds →