"Append-only means a correction REMOVES what it invalidates; it never leaves it beside the replacement."
The apparent contradiction
The storage invariant says snapshots are append-only: metric history rows carry their series, date, value, source and fetch time. Then the same invariant says a correction deletes. Read quickly, those two sentences fight.
They do not — but reconciling them takes three facts, and until 2026-08-31 the invariant only wrote down two of them. Start with the missing one, because it is the surprising part.
The third fact, which was missing
The invariant said these rows are "never rewritten". The schema says otherwise. The primary key ends in data_date and the write is INSERT OR REPLACE. Refetch the same series for the same date and the row is overwritten in place. That had been true for over three weeks while the document said the opposite.
What makes it interesting is that the code is right. The daily loop has to be re-runnable — after a retry, after a partial failure, twice in one day — without doubling a series. Overwriting on a per-date unique key is the honest way to get that; the alternative is duplicate rows and a "which of these is real" question you now have to answer on every read. That is worse.
So the real property is append-only across dates, idempotent within one. That is an idempotent upsert, not an immutable log, and the two promise different things. The sharpest consequence: if a source quietly revises a figure it already published, the next pass overwrites the old value with no trace. "What did this date say before?" is a question this store cannot answer. The principle callout below files that case under history — and in this schema, history is exactly what it does not get. The invariant had been promising something it does not keep.
What append-only is actually protecting
Append-only exists to stop silent in-place mutation of history. The failure it prevents is a value that used to be one thing and is now another, with nothing anywhere recording that it changed. That is the thing that makes a historical series untrustworthy: not that it was ever wrong, but that you can no longer tell whether what you are looking at is what was recorded.
So the rule is: you do not edit a row's value in place. New readings arrive as new rows. History accumulates rather than being revised.
What it is not
Append-only is not a rule that says every row ever written must remain forever, regardless of whether it is true. That reading turns the invariant into a machine for preserving known falsehoods — and in a store whose read model takes the newest row per series, a preserved falsehood is not an inert historical artifact. It is the answer the product gives.
Which is precisely what happened. The forward-dated rows were not "history we should keep for the record"; they described sessions that never occurred, and they sat at the front of the read model. Keeping them would have meant choosing an abstract purity over the product being correct.
What the repair looks like in practice
The repair for this incident was a named, dated script — not an interactive session with the database. That distinction matters more than it looks.
A script has three properties an ad-hoc fix does not: it states in code exactly which rows are being removed and on what criterion, it can be read by someone else before it runs, and it stays in the repository afterward as the record of what was done. When a later reader asks "why does this series have a gap in early August", the answer is a file with a name and a date, sitting in version control.