Schema honesty over aspirational naming

Schema honesty over aspirational naming

A column, type, model, or API field name is a promise about what it contains. If the name promises more than the substrate currently holds, every reader misreads it and every consumer codes against the promise rather than the reality.

Defer aspirational names until the substrate actually carries the aspirational meaning. A column named currentSha that holds a SHA is honest. A column named currentVersion that also holds only a SHA is a lie waiting to confuse the next reader.

What “schema honesty” looks like

Why this exists

Two concrete examples from the platform’s recent work:

The misnamed-schema alternative — pick the aspirational name now to “save a rename later” — produces three predictable failure modes:

  1. Every reader gets the wrong mental model. A code reviewer reads currentVersion and reasons about version semantics; the actual data is a SHA, and the reasoning is wrong.
  2. Consumers write code against the name, not the truth. A future service that depends on currentVersion being a semantic version breaks the day a SHA shows up in the field. The schema lies; the consumer crashes.
  3. The rename you “saved” still happens. When the substrate finally carries the aspirational meaning, the column has to change either way — and now it has consumers built on the wrong assumption.

When aspirational naming is acceptable

The contract

Before naming any column, type, model, or API field:

  1. Name what it holds today. Not what you hope it will hold.
  2. If the future name is different, document the rename trigger. In the spec or PR description, not as a // TODO comment.
  3. Default to the SHA-name pattern. Columns named for the literal shape of the data they hold (SHA, URL, slug, timestamp) age better than columns named for abstractions (version, identifier, name).

Anti-patterns

Spec references