Pointer: a version, not latest
Hash: detect an overwrite under the same number
Resolve: a missing version fails
Migrate: only an equivalent change moves the pointer
Coexist: old and new versions both run
A saved plan pins a semantic version instead of following latest
Saved queries change after a semantic hot update when execution rebinds them to the current definition, not only when the business data change. A saved query should pin, in its plan, the semantic versions of the metric, dimensions, filters, and grain. A new version may be published. The old plan keeps resolving to the pinned version. The pointer moves only through an explicit migration.
Which downstream consumers are affected, and how a field contract is retired, are separate governance problems. This note covers one mechanism: how a saved plan keeps the semantics it was saved with, and when that pointer may change. An unsaved exploration may explicitly request the latest version. Once the query is saved, it cannot keep a latest pointer that moves.
Pin both a version number and a definition hash
The plan should record the metric identifier and version, the dimension and entity versions it uses, definition-level filters, the aggregation, the fact grain, and a hash of the logical definition. Storing only the natural-language question or the metric name is not enough, because the name can point at a new formula after a hot update. Storing only one compiled physical statement breaks when the table layout is repaired, and it does not show whether the semantics changed.
The hash detects a definition overwritten without a version change. The version number is what people read and migrate. If the two disagree, execution fails. It does not use the new repository contents under the old number. The data cutoff is a different axis. The same semantic version on newer data can legally change the number. A semantic pin does not explain a refresh, and a refresh should not be treated as a definition change.
A missing pinned version fails the query
Resolution order is fixed. A saved plan with a version uses that version. If the version is missing, the hash does not match, or the declared grain does not match, the query fails and reports that the version is unavailable. It does not fall back to latest. Interactive exploration may explicitly ask for latest, but the save action must write the version that was resolved at that moment.
A hot update publishes a new version and makes it visible to new exploration. It does not overwrite the old version contents. The old version stays readable and executable until migration finishes. A deployment that can keep only one definition cannot pin anything; the next publish rewrites saved results. Publish the metric, dimensions, and filters as one snapshot so a new filter is not paired with an old dimension key.
Only a demonstrated equivalent change migrates automatically
Automatic migration is limited to changes that are shown to be equivalent: an alias, a comment, a materialization that does not change the logical hash, or a rewrite that matches cell by cell on a fixed data snapshot. Equivalent means the old and new versions return the same results and the declared grain, aggregation, and filters are unchanged. Equivalent does not mean the new number is a better correction. A fix for double counting changes results, so it is not an equivalent patch.
A change of grain, aggregation, definition filter, default date role, or dimension key requires an explicit migration. The migration record states the source version, target version, reason, acceptance fixture, and approver, and only then updates the pointer. Saved queries that have not migrated keep running the old version. A corrected definition does not flow into old reports by itself. Someone approves the move, or the old version remains referenced.
Bind to latest, or store an immutable pointer
Path one stores the metric name and binds to the latest definition on every run. Fixes reach every report immediately, and exploration stays simple. Saved queries then change with no migration record, and readers cannot separate an operational change, a data refresh, and a semantic hot update. Use this path only for exploration that is explicitly marked as always following latest. It is not the default for a saved report.
Path two stores an immutable version pointer and a definition hash, plus a migration ledger. Execution resolves only the pointer. Migration is a separate write. Hot updates stay isolated from saved results. A third habit is to freeze the compiled physical statement. Numbers stay still for a while, but the query leaves the semantic model, so even an equivalent physical rebuild cannot pass the same version check. Saved queries should use path two.
Publish and roll back without breaking old pointers
When a new version is published, the old version objects remain resolvable. The plan pins that snapshot, not a floating branch name. Deleting a version that is still referenced should be rejected. A rollback publishes a version the pointer can address, or reverses a migration record back to the previous version. It does not delete the new version and hope the old plan repairs itself.
The NIST AI Risk Management Framework calls for traceable measurement and change. On a semantic layer, that means each saved result can point at the definition version it used. The framework does not prescribe a version-number format, and it does not replace declarations of grain, filters, and aggregation. dbt metrics and semantic models are one way to organize the pinned objects: metrics reference measures, and semantic models describe entities, dimensions, and measures. If that organization changes, the plan still pins the definition set that was current when the query was saved.
Counterexamples and acceptance checks
Counterexample one keeps the old version number while the filter text is overwritten, the hash changes, and execution still returns the new number. Counterexample two falls back to latest when the pin fails, so every saved query changes on the day of the hot update. Counterexample three treats a result-changing fix as an equivalent patch and migrates reports with no approval. Counterexample four pins only the model package version while one metric inside the package is overwritten. Counterexample five treats a data refresh as a broken semantic pin and rebinds to the latest semantics on every load.
Acceptance: a rerun without migration keeps the plan hash, and the result is unchanged on a fixed data snapshot. After a new version is published, the old plan result is unchanged. A hash mismatch or a missing version fails and does not fall back. An equivalent rewrite moves the pointer only when the fixture matches cell by cell. A non-equivalent change keeps the old pointer and leaves a pending migration. The plan shows metric version, dimension version, filters, and grain.
BuildTable.ai boundary
Pick one saved query and freeze the data snapshot. Publish one version that only renames an alias and one version that changes a filter. Confirm that only the alias may migrate automatically and that the filter change stays on the old pin. Then confirm that a missing version or a hash mismatch does not rebind to latest. A data refresh should change the data-cutoff mark, not the semantic pointer.
BuildTable.ai can be considered as an entry point for semantic modeling. This article does not show that the current release pins saved queries to a semantic version, aggregates across facts before alignment, or implements filter-layer precedence. Inspect the saved plan for a version pointer and a definition hash, and verify it with three fixtures: no migration, an equivalent migration, and a non-equivalent change.
Public references
Build an AI-ready data foundation
Contact us to discuss your data modeling scenario and deployment support.
Contact us