16

Hyrum's Law

#
  • heuristic
  • context-dependent
  • fragment

Scope. Despite the name, this is not a measured law: it is Hyrum Wright’s generalization from years of changing Google’s shared C++ libraries, and no study quantifies it. “With a sufficient number of users” is deliberately unquantified, so it holds as a design rule that scales with the number of consumers, not as a prediction for every API. Not every observable behavior becomes a dependency — the ones that do are cheap to notice and expensive to check against the spec. The practical takeaway is not “everything will break” but “whatever you neither pin down nor randomize, someone will pin down for you”.

Conflicts with: Contract testing ↔ provider velocity

Primary sources: Hyrum Wright — Hyrum’s Law (the statement and its origin)

References: The Go Programming Language Specification, Go Blog — Go maps in action (iteration order), OpenJDK — ImmutableCollections.java (SALT, order across JVM runs)

With enough consumers, every observable property of an API is part of the contract: JSON key order, latency, error message text.

Code example (fragment)
fragment
Go
// proverb level: don't let anyone observe what you don't promise
// map deliberately randomizes iteration order: the language defends against Hyrum's Law
for k := range m { ... } // order differs on every pass; nothing to rely on
Java
// same here: Set.of()/Map.of() randomize iteration order across JVM runs
// precisely so that nobody starts depending on it

Precision. The Go spec says map iteration order is unspecified and not guaranteed to be the same from one iteration to the next, not that it is “random and always different.” The practical conclusion is the same: you must not depend on it. But the word “randomizes” describes the implementation, not the language contract.

The mechanisms also differ in strength. The Go runtime picks random offsets every time an iterator is initialized: two iterations over the same unmodified map in one process yield different orders. Java computes SALT once at JVM startup (ImmutableCollections; the source comment names the goal outright: “iteration order will vary between JVM runs”): within a run the order is stable, across runs it differs. The contract is the same for both: order is unspecified. What differs is how insistently the implementation keeps you from relying on it, and that itself may change in the next release, which is the main argument for not relying on it.

Last technical review: 2026-08-04 · Reference · 112 principles