Product systems · System · 8 min read

Historical truth is a product requirement.

A personal tracking app looks simple until yesterday’s data can change because today’s definition changed. That is where database design becomes product design.

System started as a training app, but the data model had to support more than entering numbers into a form. Exercises can be renamed. Workouts can be edited. Schedules can be archived. A user can log something offline and sync later. Analytics can compute a personal best using history that must not silently rewrite itself.

Current definitions and historical facts are different objects

If I rename an exercise from “Incline Dumbbell Press” to something else, should a workout from six months ago display the new name? Sometimes yes for convenience. Sometimes no because the historical record is evidence of what actually happened under a specific definition.

The same problem appears in business systems: product catalogs, pricing plans, customer segments, accounting classifications, or policy rules all change over time. If history points only to the current mutable definition, the past can become impossible to reconstruct.

Stable IDs are necessary but not sufficient

System uses stable identifiers so local and remote copies refer to the same logical record. But identity alone does not solve history. The product also needs rules for which properties are looked up live and which are snapshotted into an execution or observation.

DefinitionWhat the object means now.
ExecutionWhat was scheduled or performed at a particular time.
ObservationThe recorded value or state produced by that execution.
AnalyticsA derived view that must respect which version of history is authoritative.

Offline behavior makes the rule visible

Once the app can work offline, there may be a local edit that has not reached the server, a remote version changed on another device, and a historical execution that references one of them. “Just sync the latest row” is not a complete product specification.

I defined pending mutations, conflict handling, ordering rules, and explicit boundaries between current objects and historical records. Quick actions were made reversible. Archived entities could be restored under defined constraints. Invalid or incomplete observations had distinct states rather than being silently converted into zeroes.

Analytics made semantic mistakes expensive

A chart can look correct while answering the wrong question. If a personal-best calculation reads a mutable current target instead of the historical performed set, it can rewrite the user’s record without changing a single raw observation. If “skipped” and “not complete” collapse into the same state, consistency analytics lose meaning.

The rule I use: every derived metric should be traceable to the historical facts and product semantics that make it meaningful—not merely to whichever table is easiest to query.

Regression tests protect meaning, not only code

Some of System’s most useful regression tests exist because the failure would be subtle: timestamps, mutation ordering, personal-best history, offline edits, invalid observations, archived definitions, and analytics context. Compilation cannot catch those failures.

Why I think this matters beyond a personal app

Historical immutability is really an auditability problem. In finance, operations, healthcare, CRM, and analytics systems, people make decisions based on what the organization believes happened. If today’s configuration can silently rewrite yesterday’s facts, the system is not merely inconvenient—it is untrustworthy.

That is why I think of history as a product requirement before I think of it as a database implementation detail.