# Why a rank tracker should store snapshots, not recompute them

> A ranking history is a record of observations. Once a tracker recomputes it from today's index, last month's chart stops being evidence and becomes opinion.

Source: https://netweft.com/blog/snapshots-not-recomputation
Updated: 2026-02-10

**Store each rank check as an immutable snapshot — position, URL and the timestamp it was seen — rather than deriving history on read. A recomputed history can change without the SERP changing, which makes it useless as evidence.**

There are two ways to build the chart [rank tracking](/glossary/rank-tracking)
exists to draw — a keyword's position over time. You can store a row every time you look, or you can store the current
state and derive the past from it. The first is more rows. The second is
cheaper, tidier, and quietly wrong.

## What "recomputed" means in practice

A tracker that derives history keeps one authoritative record per keyword and
reconstructs earlier positions from whatever it has now — a cached
[SERP](/glossary/serp), an index snapshot, a rolling aggregate. It looks the same on screen. The
difference shows up on the day something upstream changes.

Re-run the derivation after the vendor backfills a dataset, or after your own
normalisation rules change, and last month's chart moves. Nobody edited
anything. The SERP in March did not change. But the line that described March
did.

That is fatal for the one job the chart has. You look at a ranking history to
answer *did the thing I did work*. If the history can move without the SERP
moving, the chart cannot answer that question, and you cannot tell the two
cases apart from inside the interface.

## What a snapshot is

[netweft's rank tracking](/features/rank-tracking) writes a row every time it
looks:

- the keyword and the project it belongs to
- the position that was seen, or the fact that nothing was
- the URL that held the position
- the moment the check ran

Nothing in that row is derived. Nothing recalculates it later. A month-old row
says what was seen a month ago, and if it disagrees with your memory, one of
you is wrong in a way that can be investigated rather than argued about.

The cost is rows, and rows are the cheapest thing in the system. A hundred
tracked keywords checked daily is thirty-six thousand rows a year per project,
which the database finds uninteresting.

## The missing week

The design decision that follows from snapshots is what to do when a check
comes back with nothing.

There are three tempting answers and two of them are wrong. Writing a zero is
wrong: zero is a position, and some interfaces genuinely use it, so a reader
cannot tell a rank of zero from an absence of rank. Writing nothing is also
wrong: a gap in the series is indistinguishable from a check that never ran,
which is a different fact with a different fix.

The right answer is that *not ranking* is a value. netweft stores it as a
category and draws it as one. The line does not skip the week, and it does not
dip to the bottom of the axis as though the domain were sitting at position
101. It says the domain was not in the results, which is what happened.

The same row is what an agent reads back through the API, at no charge, because
the credits were spent when the observation was taken rather than when it is
read — see [reading an SEO workspace from an
agent](/blog/reading-a-workspace-from-an-agent).

## What this buys you

Three things, all of them boring, which is the point.

A history you can quote. When you tell a client the page moved from 14 to 9 in
February, that is a claim backed by two rows with timestamps, not by a
reconstruction that might render differently next quarter.

A diff you can trust. If a row changes, something changed in the world. There
is no second explanation.

An audit trail for your own tooling. When a normalisation bug ships, snapshots
let you find the checks that ran while it was live. Derived history absorbs the
bug into the past and never mentions it again.

## The trade you are actually making

Snapshots cost storage and they make backfilling awkward: you cannot
retroactively improve a measurement you have declared to be an observation.
That is not a limitation to be engineered around. It is the property you wanted.
A measurement you can improve after the fact is a measurement, and a
measurement you cannot is a record.

netweft chose the record.
