Engineering Culture

Hyrum's Law: Every Behavior Becomes a Contract

With enough users, people depend on every observable behavior of your system, including the bugs. Your real API is bigger than the one you documented.

RE

Roberto Espinoza

CEO, Ruzora

July 19, 20268 min read

You document an API, promise a contract, and assume you're free to change anything you didn't promise. Then you change an internal detail and something breaks three teams away. Hyrum Wright, then a software engineer at Google, turned that experience into a law every engineer eventually learns the hard way: with enough users, every observable behavior of your system becomes something somebody depends on.

Key Takeaways

  • Hyrum's Law: with enough users, all observable behaviors of your system will be depended on, regardless of your documented contract (Hyrum's Law).
  • That includes timing, ordering, error messages, and outright bugs (Laws of Software).
  • Practically, there is no private implementation once usage is large enough.
  • It came from Hyrum Wright's experience doing large-scale infrastructure migrations at Google.

The Law

Hyrum Wright's formulation is precise: 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 (Hyrum's Law). The law came out of his work on low-level infrastructure migrations at Google, where changing a seemingly trivial detail in a library would break distant systems nobody knew were coupled to it.

The key word is observable. Your documented contract might say "returns a list of users." But if that list has always come back sorted, someone is depending on the sort order. If an error message has always contained a particular string, someone is parsing it. If a call has always taken under 50 milliseconds, someone's timeout depends on it. None of that is in the contract. All of it is now load-bearing.

Bugs Become Features

The most uncomfortable corollary: even your bugs become dependencies (Hyrum's Law explained). If a function has always returned an off-by-one result and consumers have quietly compensated for it, fixing the bug breaks them. This is why large systems end up with "bug-for-bug compatibility," where correct behavior means whatever the old version did, mistakes included. The gap between your documented interface and your actual, implicit interface widens with every user.

What you documentedWhat people actually depend on
Returns a listThe order it comes back in
Returns an errorThe exact error message text
Returns a valueHow long it takes
The specified behaviorThe bugs, too

A Concrete Version

A team owns an internal API that returns search results. The docs say nothing about ordering, so when they swap the underlying index for a faster one, they consider it a safe, invisible change. Two days later a billing report is wrong, because a downstream team had been taking the first result and assuming it was the most recent, since it always had been. Nobody documented that assumption, nobody promised it, and it was still real. The "internal implementation detail" was a contract the whole time.

What to Do About It

Hyrum's Law is a fact of gravity rather than a problem to solve, so the response is defensive. Make the behavior you don't want depended on hard to depend on: randomize what should be unordered, so nobody can rely on an accidental order. Keep interfaces small, since fewer observable behaviors mean fewer implicit contracts. Version deliberately, and treat any change to widely-used code as a change to an implicit interface you can't fully see, which is exactly why Chesterton's Fence applies so strongly to shared code. And where you can, measure who's actually calling what before you change it.

The Honest Counterpoint

Taken too far, Hyrum's Law becomes an excuse to never change anything, which calcifies a system just as surely as reckless changes break it. The law describes systems with enough users, and most internal code doesn't have that many. A service with three known consumers is a different problem from a library with ten thousand, and treating them the same wastes enormous effort. The useful reading is proportional: the bigger the blast radius, the more you should assume undocumented behaviors are load-bearing, and the more you should invest in deprecation paths over clean breaks.

What This Means for Teams

Hyrum's Law is one of those things engineers learn by breaking production once, and it shapes how carefully someone treats shared code. Senior engineers instinctively ask "who depends on this, and what have they noticed about it?" before changing a widely-used interface, which is the same understand-before-you-change judgment that makes legacy work safe. That instinct is hard to teach and easy to test for, and it's part of what we screen for in how to verify a senior engineer. See available engineers.

Frequently Asked Questions

What is Hyrum's Law?

Hyrum Wright's observation that with enough users of an API, every observable behavior of your system will be depended on by someone, regardless of what your documented contract promises.

Does that include bugs?

Yes. Consumers compensate for buggy behavior, so fixing the bug breaks them. This is why large systems end up with "bug-for-bug compatibility," where correct behavior means whatever the old version did.

How do I protect against it?

Make undesirable dependencies hard to form: randomize what should be unordered, keep interfaces small, version deliberately, and measure who actually calls what before changing widely-used code.

Does it apply to small internal services?

Less so. The law describes systems with enough users. A service with three known consumers is a much smaller problem than a library with thousands, so scale your caution to the blast radius.

The Bottom Line

Your real interface is bigger than the one you wrote down: with enough users, the ordering, the timing, the error strings, and even the bugs become contracts someone depends on. Treat changes to widely-used code as changes to an invisible interface, make accidental dependencies hard to form, and scale your caution to how many people could break.

Roberto Espinoza is CEO of Ruzora, which helps US startups hire pre-vetted senior LATAM engineers in 72 hours. See available engineers.

RE

Roberto Espinoza

CEO, Ruzora

Roberto is the founder and CEO of Ruzora. He works directly with US startup founders and CTOs on staff-augmentation and software-factory engagements, and personally reviews senior engineer placements.

AI-vetted engineers, ready now

Your next senior engineer is already vetted and waiting.

It starts with a single call. 72 hours later, you're reviewing scored candidates who already match your stack and culture.