Navigate
HomeStart here
MusingsResearch & long-form
BuildingProjects & learnings
WorkProfessional practice
RunningTraining & races
AboutValues & identity
Notes & ArchiveJournals, essays, portfolio
← Back to Building
PATTERNJul 2026

The Gate Watched One File While Fifteen Rotted

My running page served four-month-old numbers while the freshness check passed green. The check only watched the files someone had remembered to register.

data-syncfreshnessbuild-gatesstravafailure-mode

The Strava snapshot behind my running page went stale in March. Nobody noticed until late June, because the page rendered fine: real mileage, real paces, plausible charts. The data was just four months old. This was the second time this exact class of bug hit the site. The first time it was music play counts, and after that incident I wrote the rule: sync-fed data files need freshness checks. The rule existed. The Strava file rotted anyway.

The problem was that the freshness gate watched an explicit list of files, and the list had one entry. The site had roughly fifteen data files being fed by crons, webhooks, and manual syncs. Every new one depended on someone remembering to register it. A gate that relies on memory is a to-do list with better branding.

The fix inverts the burden. The check now scans every data file for the shape of a sync timestamp: fields like a last-sync date or a latest-record date. Build stamps do not count, because a file can be regenerated at deploy time while its actual contents stay frozen; a fresh timestamp on stale data is worse than no timestamp. Any file carrying a real sync signal must be either watched with a max age or explicitly exempted with a written reason. A file that is neither fails the build. There is no third state, which means there is no silent state.

Then the same idea generalized: an external-pipeline contract registry. Every outside dependency (an API, a token, a cron) enrolls in the registry with its expected cadence, or the build fails. The pattern underneath both is the same one I keep relearning: a rule that lives in documentation catches nothing. Most of my recurring defects had an existing rule at the time they recurred. The bottleneck is never knowledge. It is whether the rule can fail a build.

// A freshness gate that relies on memory:
watched = ['data/music.json']        // registered after incident #1
// data/strava.json rots for 4 months, check stays green

// A freshness gate that enforces coverage:
for (file of allDataFiles) {
  if (hasSyncTimestamp(file)) {      // lastSync / latestDate
    // generatedAt is a build stamp, not an honest signal
    assert(watched(file) || exemptWithReason(file))
    // neither -> the BUILD fails, not a dashboard tile
  }
}