Skip to content
Part IA Easter Term

Hyrum's Law and the Deprecation Path

Hyrum’s Law

Hyrum Wright, a software engineer at Google, observed:

With a sufficient number of users of an API, it does not matter what you promise in the contract: all observable behaviours of your system will be depended on by somebody.

This is not a cynical joke; it is an empirical observation about how large-scale software ecosystems actually behave. Even if your documentation explicitly states “the order of returned results is undefined and should not be relied upon,” at sufficient scale, someone’s integration test depends on the specific order that happens to be produced. When you change the ordering algorithm in a PATCH release, their CI pipeline breaks — and from their perspective, you broke it, not them, because “it worked before the upgrade.”

The SimCity / Windows 95 Hack is the classic case study. During Windows 95 development, Microsoft discovered that the game SimCity crashed on the new OS due to a memory management bug in the game itself. Rather than let one of the world’s most popular games break on their flagship OS, Microsoft added special-case code to the Windows 95 kernel: “if the running application is SimCity, use a special, slower memory allocator that masks the game’s bug.”

The takeaway: once you have enough users, every bug becomes a “feature” that someone depends on. This is why breaking changes and migrations are so difficult — you are not just changing the documented contract; you are breaking an uncountable number of undocumented, implicit dependencies that real systems rely on in production.

The Deprecation Path

Because many users depend on undocumented behaviour (Hyrum’s Law), you cannot simply delete an old endpoint, rename a function, or change a parameter type overnight. The responsible approach is a phased deprecation path:

  1. Announce — publish a notice that the feature (or the old endpoint, or the legacy format) will be removed in a future version. State the timeline explicitly: “this will be removed in version 4.0, expected Q3 2026.”

  2. Deprecate — mark the API as @Deprecated (in languages with annotations) or add a Deprecation HTTP header. The old functionality continues to work alongside the new one. Compiler warnings, runtime logs, and documentation all steer users toward the replacement. This is typically shipped in a MINOR version (the old API still works — it is backwards-compatible).

  3. Wait — give users a migration window: 6–12 months, or several minor versions. During this window, both old and new APIs coexist. Users migrate at their own pace. Usage of the deprecated API is monitored; when it drops to near-zero, the window closes.

  4. Remove — in a new MAJOR version, delete the deprecated code. Any remaining users who did not migrate will experience a breaking change on upgrade — but they had 6–12 months of warnings and working alternatives.

This is why you cannot simply turn off an XML API endpoint tomorrow and replace it with a JSON one. Doing so would be an uncommunicated, no-window breaking change, instantly breaking every customer’s CI/CD pipeline and production system without warning — a violation of Postel’s Law and of the API-as-contract principle.

Hyrum’s Law in a CI/CD World

If you ship a breaking change without warning, every downstream consumer whose CI/CD pipeline tests against your API will experience failing builds the moment your change reaches them. Their automated tests assert “given XX, get YY”; your change breaks YY; their Quality Gate fails; their build is rejected. You have propagated your internal change into an involuntary production incident for every one of your consumers, simultaneously.

Expected Learning

  • State Hyrum’s Law and explain its implications for API evolution.
  • Describe the SimCity/Windows 95 hack and what it demonstrates about implicit dependencies.
  • List the four steps of the deprecation path and explain why each is necessary.
  • Explain why an abrupt breaking change propagates through consumers’ CI/CD pipelines as cascading failures.
  • Justify why deprecation requires a MINOR version (add the replacement, keep the old), and removal requires a MAJOR version (break the contract).

Past Paper Questions

Example Sheet 2, Question 9(a) asks about turning off an XML endpoint tomorrow — testing whether you understand that this is an uncommunicated breaking change with no deprecation path. Example Sheet 2, Question 7(c) tests Hyrum’s Law in the context of migrating a 30-year-old COBOL mainframe system.