# Hyrum's law

> With enough users, every observable behavior of your API is depended on by someone, whatever the contract says.

Concept · Laws of software engineering · https://levelcode.org/concepts/hyrums-law

**Hyrum's law**, named for Hyrum Wright at Google, says: 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 documented interface is only part of the real interface.

## How it works

Users don't read your contract. They read your responses. Anything they can observe, they can come to rely on, usually without noticing:

- **Ordering.** A list endpoint happens to return rows by ID. A client starts using the first element as "the oldest".
- **Error text.** A caller matches on `"user not found"` in the message instead of checking a status code or error type.
- **Timing.** A job always finished in under a second, so a caller stopped waiting for it properly.
- **Field shape.** A number that was always an integer gets parsed into an `int`, and breaks the day you send `3.5`.

None of these were promised. All of them become breaking changes once enough people depend on them. The number of users matters: with ten callers, you can ask them. With ten thousand, someone always relied on the thing you changed.

## Living with it

You can't prevent it, but you can shrink the surface:

- **Don't expose what you don't need to.** Every extra field, header or ordering is a future promise.
- **Randomize what you don't guarantee.** Go randomizes map iteration order on purpose, so no program can come to depend on a stable order.
- **Return structured errors.** Give callers a code to match on so they don't parse your messages.
- **Change in steps.** Add the new behavior, measure who still uses the old one, then remove it, the same [expand–contract](https://levelcode.org/concepts/expand-contract-migrations) pattern used for schemas.
- **Version deliberately.** A new [API version](https://levelcode.org/roadmaps/go-backend/rest-api-design) lets you change behavior without breaking callers who never asked for it.

Before you call a change "not breaking", ask what a client can observe, not what the docs say.
