Laws & Disorder #2 — Hyrum's Law: In the Age of Agents, Who Pays for a Broken API?
written by Stefan Christoph
- 9 minutes readSecond in “Laws & Disorder,” the series on the software laws we half-quote. Last time it was Conway’s Law. This one is the reason your “non-breaking” change broke someone anyway.
There is a particular kind of production incident that teaches you humility. You ship a change that is, by every reasonable reading of the documentation, backward compatible. The spec is unchanged. And something downstream falls over anyway, because a consumer was quietly depending on a behavior you never promised and never knew they could see.
That is Hyrum’s Law, and once you have been on either side of it you stop trusting the phrase “non-breaking change.”
The law
Hyrum Wright, an engineer at Google, noticed around 2011 that even internal library changes that should have been invisible kept breaking some project, somewhere. Titus Winters later wrote it down in “Software Engineering at Google” [2], and it now lives at its own one-line address [1]:
With a sufficient number of users of an API, it does not matter what you promise in the contract: all observable behaviors of your system will be depended on by somebody.
The key word is observable. Not documented. Observable.
The docs are not the contract
The canonical example is a list. Your documentation says the order is unspecified. But in practice the implementation returns it sorted, and it has for years. Somewhere a consumer wrote code that assumes sorted order, because that is what they observed. The day you “fix” the implementation to truly randomize the order, per your own spec, you break them. You were right on paper and it did not matter.
It is never only ordering. It is the exact wording of an error message that someone is string-matching on. It is the retry timing that a client tuned its own backoff against. It is a field that is always null in practice so nobody handles the non-null case. xkcd captured the whole law in one strip: somewhere, someone’s workflow depends on your CPU running hot because they hold down the spacebar to keep the room warm, and the moment you optimize it you have broken their setup [3]. The joke is that this is not a joke.
Internal APIs are contracts too
Here is the part I learned the expensive way. For a stretch of my career I was responsible for API strategy at a large company, and we did what almost everyone does: external APIs got the effort. They got the documentation, the versioning discipline, the deprecation notices, the careful reviews, because customers were on the other end. Internal APIs, the ones between our own teams and services, were treated as second-class. Move fast, we own both sides, we can just fix the callers.
Except a broken internal contract caused just as much damage. When an internal API changed a behavior a sister team had come to rely on, the outage was just as real, the debugging just as painful, and the blast radius sometimes larger because internal callers had fewer guardrails. Hyrum’s Law does not check whether an interface is public before it applies. Given enough consumers, if someone can observe a behavior, someone will depend on it, and “internal” does not exempt you. All APIs are contracts. The internal ones simply have the same law applied with less of a safety net.
Why the big platforms move slowly
If you have ever been frustrated that a cloud provider takes years to deprecate anything, Hyrum’s Law is a large part of the reason, and it is a feature. When your API has enough users, you cannot know which observable behaviors have become load-bearing, so you keep them, sometimes bug-for-bug, and you deprecate on long, telegraphed timelines. That caution is not sluggishness. It is what reliability looks like from the inside.
A clean example is Amazon S3 consistency. For years S3 offered eventual consistency for certain operations, and applications built around that behavior, some depending on it in subtle ways. In December 2020 S3 moved to strong read-after-write consistency, at no additional cost and with no performance penalty [5]. The scope is worth stating precisely, because it is narrower than “everything”: the guarantee covers PUT and DELETE requests for objects, along with reads of object metadata, tags and ACLs. Bucket configurations are still eventually consistent — delete a bucket and it may briefly keep showing up in a listing [5].
The Hyrum’s Law angle is more interesting than “a strengthening is always safe.” It is tempting to say a strengthening can only remove surprises and never add them, but that is exactly the reasoning this law warns against. Anything that made the eventual-consistency window observable — a retry loop that expected the occasional miss, a workflow that leaned on a new object not appearing in a listing straight away — now sees behavior it never saw before. AWS designed the transition to preserve documented compatibility, and that is what made it safe to ship at this scale; not some general rule that strengthening is harmless. (As of 2026 that strong-consistency behavior is the default and documented model [5].) Contrast that with a change that removes a behavior someone observed, which is the kind these platforms guard against for years.
Before: a loud break, fixed once. With agents: a quiet workaround, paid for on every call.
The AI twist: a loud failure traded for a quiet tax
Now the forward-looking part, and I want to be clear this is reasoned analysis as of 2026, not a benchmark.
The old sequence, at least in the clean case, was blunt but honest. An API changes, the integration breaks loudly, a developer sees the failure, and fixes it once, usually by adopting a versioned client library. After that the behavior is deterministic and stable. The pain was visible and it was one-time.
Some APIs are now abstracted behind layers like MCP and consumed not by a developer writing a client, but by an AI agent [4]. And an agent can do something a typical static client does not: when it hits a changed API, it can attempt to work out its own way around the change at runtime, generating glue code on the fly. Conventional clients are not incapable of adapting — feature detection, version negotiation and fallback paths all exist — but those adaptations are ones a developer anticipated and wrote down in advance. When the agent’s workaround succeeds, the end user never notices the break. On the surface this looks like pure resilience, and that resilience is a genuine benefit. I am not arguing agents are bad here.
The point is what the flexibility costs. That workaround is generated, and — depending on whether the agent caches it — it may be regenerated on every call. Each generation costs inference latency and spend for glue that a versioned library would have handled with a one-time integration cost — paid once, not per call. And each of those workarounds is bespoke and non-standard. The generated program itself runs deterministically once produced — what varies is the generation step, so the same changed API can yield a different workaround on a different call unless you cache and test the result. It is not a well-tested library with a stable contract. That raises the odds of behavior that is subtly wrong, and wrong differently from one call to the next. Agents take a hard, visible failure, the kind you fix once, and turn it into a soft, recurring, variable tax you might not even see on the invoice for a while.
Which is the opposite of “MCP and agents make versioning obsolete.” They make API discipline matter more, because the failures they paper over are the ones that used to force you to fix the root cause.
If you’re running this on AWS
- Version explicitly. Use API Gateway stages and versioned routes so a change is a new version, not a silent mutation of an existing one. Consumers opt in.
- Test the contract, not just the code. Consumer-driven contract tests [7] catch the moment a downstream team starts depending on a behavior you consider incidental — provided the consumer encodes that expectation in a published contract and you verify against it.
- Deprecate on evidence. Instrument real usage so you deprecate based on who actually calls what, not on what the docs say is safe to remove. This is exactly where usage telemetry earns its keep.
- Apply all of this to internal APIs too. They are contracts. Give them the versioning and telemetry you give the external ones, because Hyrum’s Law does not care about the org boundary.
Your API’s real surface area is not what you wrote down. It is everything a consumer can see, human or agent. So before your next “safe” change, the honest question is not “does this match the spec?” It is “what can someone observe today that they might already be leaning on?”
What behavior in your system is documented as an implementation detail, but has quietly become a contract?
More in this series
Continues from Conway’s Law and leads into Tesler’s Law (you can’t delete complexity, only choose who owns it). Sparked by the Laws of Software Engineering collection [6].
Sources
- [1] Hyrum’s Law — the canonical one-line statement.
- [2] Software Engineering at Google — Hyrum’s Law — the origin and the reasoning behind it.
- [3] xkcd 1172 — Workflow — the “spacebar heating” strip that captures the law perfectly.
- [4] Model Context Protocol — the spec behind APIs being abstracted for agent consumption.
- [5] Amazon S3 — data consistency model — strong read-after-write consistency since December 2020 for object PUT and DELETE requests, plus reads of object metadata, tags and ACLs, at no extra cost; bucket configurations remain eventually consistent.
- [6] Laws of Software Engineering — Hyrum’s Law — the collection that sparked this series.
- [7] Consumer-Driven Contracts: A Service Evolution Pattern — Ian Robinson on the pattern behind consumer-driven contract testing.
About the Author
Stefan Christoph is a Principal Solutions Architect at AWS, focused on agentic AI, media & entertainment, and helping builders move from demo to production. He writes about AI architecture, developer productivity, and the future of software.
This is a personal blog. Opinions expressed here are my own and do not represent the views or positions of my employer.
Cross-posted to LinkedIn
🎬 Also available as a blog walkthrough video on YouTube
❤️ Created with the support of AI (Kiro)
📝 Last updated: August 13, 2026 — Technical corrections from a quality audit