Real Loss or Stale Read? The Night the Records Vanished, and the Dashboard That Lied Both Ways

Date:

The system said the records were gone. They really were gone. But the same system routinely reports counts that are wrong by a factor of eight — so how do you know which kind of “gone” you are looking at, before you act on it?

The short answer: When a remote system reports data missing, two opposite things are possible: it is genuinely lost (recreate it) or the read is stale and the data is fine (recreating makes duplicates). An unreliable system produces both signals, so one alarming read proves nothing. In one incident 29 records were truly gone by evening — a search returned zero, the count was short by exactly 29 — yet the same dashboard on other days reported totals wrong eightfold. What distinguished real loss from bad read was a local ledger the remote system could not touch plus arithmetic: the recovered count matched the loss exactly, which caching coincidence would not. Trust the record you control, confirm across time and a second view, and never mass-recreate on one read.

The system of record is the one authoritative store of a fact; a stale read is any view that can report that fact incorrectly because it is cached, replicated, or eventually consistent.

The incident, in numbers

The morning run created 29 records in a third-party system. Every one returned success; the local log recorded 29 creations.

By evening they were gone — not “looked gone in one place”, gone. A directory search for a record made that morning returned zero matches, and the system’s own roster showed a count 29 short of where the morning had left it. Two independent reads agreed the work was missing.

So it was recreated: 25 of the 29 went back in, each confirmed present immediately after; the rest were already accounted for. Afterward the roster told the whole story at a glance:

  • morning total after creation: 29
  • evening roster: the 29 absent
  • records recreated: 25
  • roster after recovery: 54

Fifty-four is twenty-nine plus twenty-five. The recovered total is fully explained by the original work plus the recovery — which means nothing “came back.” The loss was real, and the recreation was the right call.

The recovered count equalled the loss plus the recreation, exactly. Nothing had returned on its own.

The belief I had to correct

Here is the uncomfortable part, and the reason this incident is worth writing down.

My first recorded conclusion was the opposite: that the data had not been lost, that the system had merely suffered a transient read glitch, and that the records had reappeared on their own. That note carried a clear instruction to a future reader — do not recreate on a missing read, you will make duplicates.

That conclusion was wrong, and the arithmetic above is what disproves it. If the records had reappeared, the evening roster would have climbed back toward 29 on its own and the 25 recreations would have pushed it to something near 54 with duplicates. Instead the numbers were clean: 29 lost, 25 recreated, 54 total, and — checked weeks later against a full crawl — exactly one record per identity, zero duplicates. The records did not reappear. They were recreated, correctly, once.

I let a plausible story (“eventual consistency, it’ll settle”) override the ledger. The ledger was right the whole time.

A plausible explanation that contradicts your own arithmetic is a story, not a diagnosis.

Why both readings were credible

What makes this genuinely hard — not just a lesson in carelessness — is that the “transient glitch” theory was not stupid. The same system’s read layer is unreliable, and I had the evidence to prove it.

On other runs, the roster reported 20 users while the local ledger held 165. It reported 80 one minute and 201 the next, with no writes in between. Those are not real changes; they are a read layer serving stale or partial views. Anyone watching those numbers learns, correctly, that a low read is often a lie.

So the environment trained me to distrust exactly the signal that, this one time, was telling the truth. That is the core difficulty: a system that usually lies about loss can still, sometimes, actually lose your data — and the two cases present identically in a single glance.

The environment trained me to distrust the one signal that, this time, was true.

How to tell them apart — before you act

The resolution is not “trust the system” or “distrust the system.” It is to stop relying on the untrustworthy view for a decision this consequential.

  1. Keep a local ledger the remote system cannot touch. The one artifact that survived the wipe was the local record of what had been created. It is the anchor every other decision hangs from — without it, “is this loss real?” has no reference point. This is the same instinct as trusting the authoritative store over a cached count: the number you can reconstruct beats the number you are shown.
  1. Confirm across time and a second view. A single read is an opinion. The loss here was believed only after a search and a roster count agreed, and stayed agreed. When the two disagree, or one settles on a re-check, you are looking at a stale read, not a loss.
  1. Do the arithmetic, and let it overrule the story. Counts that add up cleanly (loss + recovery = total, no remainder) confirm a real loss; counts that overshoot reveal duplicates from acting too soon. The math is a harder authority than any narrative about consistency.
  1. Never mass-recreate on one read. The expensive failure mode is recreating on a false alarm and doubling your data. The check that makes recreation safe is a per-item existence test against the system of record — reconcile before you recreate, recreating only the genuinely absent and verifying each after.

What the ledger cannot do

A local ledger tells you what should exist; it cannot, by itself, tell you what does exist in the remote system at this instant — that still requires a read, and the read is the unreliable part. The ledger’s job is narrower and vital: it converts an unanswerable question (“is this loss real?”) into an answerable one (“does the authoritative store match my record, confirmed twice?”). It also cannot prevent the loss; nothing here would have stopped a downstream wipe. What it prevents is the second disaster — the duplicates you create by reacting to the first one badly. Detecting the loss and reacting safely are different problems, and only the ledger-plus-arithmetic discipline solves the second.

A record a check flags as wrong is often the same illusion in another guise — the code moved ahead of a stored copy an incremental gate skipped, not corruption; see The fix that didn’t take.

The short version

Twenty-nine records created in the morning were genuinely gone by evening; a search and a roster count agreed, and recreating 25 of them (the rest already present) was correct — proven because the resulting total, 54, was exactly 29 plus 25, with zero duplicates on a later full crawl. My first conclusion had been the opposite — a transient read glitch, records “reappeared”, do not recreate — and it was wrong, overturned by that arithmetic. The reason both readings were credible is that the system’s read layer genuinely is unreliable (it reported 20 against a real 165, and 80 then 201 with no writes). The discipline that resolves it: keep a local ledger the remote system cannot touch, confirm across time and a second view, let the arithmetic overrule the story, and never mass-recreate on a single read.

Frequently Asked Questions

How do I know if data is really lost or just not showing up?

Do not rely on one read. Confirm the absence across time and through a second, independent view — a search and a count, minutes apart. A real loss stays absent under every check; a stale read disagrees with another view or settles when you look again. And reconcile against a local record of what should exist, so “missing” is measured against an anchor the remote system cannot alter.

Why is recreating missing data dangerous?

Because if the data was not actually lost — only mis-reported — recreating it produces duplicates in the system of record, which is often harder to clean up than the original scare. The safe form is a per-item existence check: recreate only the records genuinely absent from the authoritative store, skip those present, and verify each afterward.

What is a system of record, and why keep a separate ledger?

The system of record is the one authoritative store of a fact. A separate local ledger is your own log of what you did to it — what you created, when. It matters because when the system of record becomes unreadable or loses data, the ledger is the only surviving reference for what should be there, turning an unanswerable “is this real?” into a checkable comparison.

Can a system both lose data and report false counts?

Yes, and that combination is the hardest to reason about. A read layer that is cached, replicated, or eventually consistent can serve wrong counts routinely; that same system can also suffer a genuine loss. Because the two present identically in a single glance, an environment full of false alarms trains you to dismiss the one alarm that is true.

How did arithmetic prove the loss was real?

The recovered total equalled the original count plus the number recreated, with no remainder — 29 plus 25 equalled 54. Had the “records reappeared on their own” theory been true, the recreations would have pushed the total past 54 into duplicate territory. A later full crawl showed exactly one record per identity, confirming the clean sum and refuting the reappearance story.

What should I do the moment a system reports missing data?

Stop before acting. Record the reading, then take a second one through a different view and after a short interval. Compare both against your local ledger. Only if the absence is consistent across views and time, and the ledger agrees the records should exist, do you recreate — and even then item by item with an existence check, never as a bulk re-run on the strength of the first alarm.

Share post:

Subscribe

Popular

More like this
Related

How to Merge Spreadsheets by URL (and Why Our Tool Reported 5 Misses That Weren’t)

Matching two spreadsheets on a URL column is the same job as matching a stock list to a price list by product code. It goes wrong in the same two places: how you clean the code, and how you count what didn't match.

Many-to-One: Why a Mapping Backlog Outgrows Its Target Taxonomy

You're mapping a messy source vocabulary onto a clean target taxonomy. The target has about 5,600 slots, so the job must be roughly 5,600 decisions — right? The backlog is already past 8,900, and still climbing.

The Fix That Didn’t Take: When a Content-Hash Gate Skips Your Code Change

You shipped a fix to how one field is computed, re-ran the pipeline across everything, and it reported a clean run. Then the consistency check still flags those records as wrong. The fix is in the code, the rebuild "ran" — and the records never changed. Your own optimisation skipped them.

Your Dedup Scan Is Over-Counting — Because It Forgot What You Already Fixed

The report said 80 duplicate groups still to resolve. You'd been resolving them for days. You run it again after a big batch and it *still* says 80-ish. The backlog isn't stubborn — the scan is counting work you already finished.