Build1 publisher3 min readPublished
Data agents need dated, approved metric versions to answer historical revenue questions
Data agents must resolve each metric by version and effective date, a dev.to post argues, using a Revenue v3-to-v4 redefinition as its test case. Otherwise a Q1 question asked in September gets whatever definition the registry happens to hold that day.
The Engineer · Build desk

What happened
- Overwriting a static registry entry loses the prior definition, its effective date, its approver, and the record of which answers used it.
- The proposed fix keeps one stable metric identity with immutable versions, each carrying an owner, a status, and effective_from and effective_to dates.
- Publication time and business time are tracked separately, since Finance might approve a definition on June 10 that takes effect from June 1.
- Historical questions need an explicit as_was or restated policy, and the post says asking the user beats guessing when that policy is unclear.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
- exposure Answers given during a backdated window change when re-asked, and without a per-answer version log the ones that went out on v3 cannot be traced.
- decision Governance owners have to assign as_was or restated to each metric, and for cross-period comparisons choose between mixed definitions and restated figures.
- cost Table moves such as Product Code's switch to product_dim need the same versioning and approval as formula changes, even though no business meaning changed.
The dev.to post's objection to a lookup written as `registry.get("revenue")` is that it takes a metric name and nothing else [7]. Its replacement, `registry.resolve(metric_id="revenue", effective_at=query_time)`, takes a name and a time [7]. Every path from intent resolution to query plan now has to carry that time. A path that drops it returns one version for every period, whatever the question asked.
Backdating is where the two timelines collide. In the post's example, Finance approves a definition on June 10 and makes it effective from June 1 [6]. For 9 days, v4 is the correct definition and v3 is the published one [1]. A question about June 3 asked on June 5 resolves to v3. The same question asked on June 12, resolved by effective date, returns v4 [2]. The two answers differ by the approved adjustments [1]. Nobody touched the SQL, and someone in Finance will still ask why early June moved.
The post lists "which answers used the old definition" among the facts an overwrite destroys [4]. An append-only registry keeps the definitions. It does not record which version produced each answer. I'd have the resolver write the metric_id and version beside every answer it returns. Without that log, the June 5 answer cannot be found after v4 lands [2].
The schema has one seam I would settle before adopting it. The v4 record keeps its end date on the row, as `effective_to: null` [5]. When v4 publishes, v3's range has to close on 2026-05-31 or the two versions overlap [3]. Closing it means editing a record the post says to leave alone: "Do not mutate v3 into v4." [5] That instruction is aimed at the definition, and an end date is arguably metadata. In my view the cleaner design is append-only rows, with each version's end computed from its successor's effective_from at resolve time.
Physical mappings need the same treatment. The post's Product Code example moves from `product_master.material_id` to `product_dim.product_code` [10]. That change leaves the business definition alone and rewrites every query that touches the term. The post's chain puts Approval State ahead of Physical Mapping [11], so a table move should pass the same approval as a formula change.
The as_was and restated policies [8] are the expensive part to adopt, because each is a decision a person makes per metric. On comparisons, the post shows neither option is free. Using v3 for Q1 and v4 for Q3 breaks consistency, while restating Q1 under v4 yields a number the organization never reported [9]. The author wrote: "This decision belongs in business governance. The LLM should not invent the policy." [9] The post's fallback, asking the user when the policy cannot be determined safely, is the right default for an agent [8].
The post describes a pattern. It does not include resolver code or measurements from a production registry.
What to watch
- Whether the author publishes resolver code, and how it closes a superseded version's effective_to without editing an immutable record.
- How the pattern handles dimensions such as Region and Business Unit, where a changed mapping regroups historical rows instead of recomputing a sum.
- Any report of how often an agent built this way has to stop and ask the user which historical policy applies.