3 April 2026
The KPI that moved because of a join
A six-point swing in conversion, no release notes, a very quiet Tuesday. The feature flag board was empty. The join was not.
The team had a live conversion tile that joined checkout events to a users_current table. “Current” meant whatever row existed at query time. Overnight a backfill corrected plan codes for a slice of accounts. Yesterday’s events, replayed through today’s dimension, changed category. The wall moved. Product was asked what they shipped. They had shipped nothing.
In real-time app KPI tracking this is a classic poison: a stream of facts joined to a slowly changing lookup that is allowed to rewrite the past. Streaming engines will happily do it. The KPI contract will not, unless you say so out loud.
Clinic markup for this case was three questions. May this join move a number that has already been quoted in a board pack? If yes, who signs the change log? If no, do you pin the dimension as of event time, or do you freeze a daily snapshot and accept that “live” stops at the snapshot’s edge?
None of those answers is free. Pinning event-time attributes is slower to build. Snapshots are easier and slightly less live. Pretending the join is innocent is the expensive option, because it spends trust.
If your tile cannot survive a dimension backfill without a human explanation, it is not a KPI yet. It is a query with fans.