dbt metric definitions make a calculation reusable through the dbt Semantic Layer, but reuse turns a convenient YAML object into an interface. Once dashboards, notebooks, and applications request a metric by name, changing its grain, entity joins, time dimension, filter, or null behavior can change decisions without breaking compilation. A versioned analytics contract treats semantic code with the same care as a production API: stable identity, documented behavior, compatibility classification, tests, ownership, and deprecation.
The dbt documentation current in July 2026 describes semantic models as the foundation for MetricFlow, entities as join concepts, dimensions as grouping and filtering concepts, and several metric types including simple, ratio, cumulative, derived, and conversion. Those primitives define what a query engine can calculate. Teams must add the business controls that explain what should remain stable and what evidence is required before a definition changes.
Write the business contract before YAML
Begin with a plain-language statement: what decision the metric supports, who owns that decision, what event or state is counted, the population included and excluded, the unit, expected direction, and known limitations. Name the accountable business owner and technical maintainer. Record whether historical values can restate after late data or source correction. A precise contract prevents a syntactically valid metric from formalizing an unresolved argument.
Define the observation grain. Revenue per order, per line item, and per payment are not interchangeable. State whether the metric is additive across time, entities, and dimensions. Ratios need numerator and denominator populations; conversion needs base event, conversion event, entity, and window; cumulative metrics need a window or grain-to-date rule. Give two worked examples that include edge cases, not only a happy round number.
| Contract element | Question | Example evidence | Breaking if changed? |
|---|---|---|---|
| Grain | What does one measure row represent? | One row per completed order | Usually yes |
| Entity | What joins observations across models? | Stable customer ID | Usually yes |
| Time | Which timestamp and calendar apply? | Paid time in UTC, fiscal month | Yes |
| Population | Which records are included? | Exclude test and cancelled orders | Often yes |
| Null rule | Is missing zero, unknown, or excluded? | Unknown cost excludes margin | Often yes |
Model grain, measures, and source quality
Choose a dbt model whose rows support the promised grain without fanout. Declare measures and dimensions only after testing source uniqueness, non-null keys, accepted categories, and referential behavior. A semantic runtime cannot rescue a base model that duplicates an order when joined to payments. Keep transformations that establish canonical business state in tested dbt models; keep metric composition in the semantic definition. This separation makes source correction and metric meaning independently reviewable.
Document measure aggregation and non-additive behavior. A balance should not be summed across dates, and a distinct customer count cannot be freely added across regions. The dbt metric specification supports type-specific controls, but the contract should explain their business purpose. Validate totals at supported grains and reject or warn on unsupported combinations where the interface allows it. Avoid publishing every available column as a dimension because each creates a compatibility, performance, and privacy obligation.
Use entities as governed join paths
dbt semantic models identify primary, unique, foreign, and natural entities. Select entity names that represent stable business concepts across models, and test the underlying keys according to their declared cardinality. A primary entity should identify one record per row in its model. A foreign entity can repeat, but joining through it may alter grain. Do not declare an entity solely to make a desired query compile; prove that the relationship preserves the metric's intended population.
Maintain a join-path review for cross-domain entities such as account, user, order, and subscription. Multiple valid paths can produce different answers. Prefer one approved path for a governed metric, or expose separate named metrics when the business meanings differ. Test fanout with adversarial fixtures: multiple subscriptions per account, transferred ownership, missing dimension rows, and type-II history. A path change is a contract change even when all field names remain stable.
Specify dimensions and time semantics
Dimensions determine how a metric can be grouped and filtered. Define categorical values, null or unknown category, slowly changing behavior, access classification, and allowed cardinality. dbt documents support for time and categorical dimensions and for joins to type-II slowly changing dimensions. If a customer's region changes, decide whether historical revenue follows the region at transaction time or the customer's current region. Both can be useful, but one unnamed choice cannot satisfy both analyses.
Name the aggregation time dimension, source time zone, conversion point, supported granularities, week start, fiscal calendar, and period-completeness rule. Distinguish event time from ingestion and model update time. Define daylight-saving behavior for local calendars. For cumulative or comparison metrics, state whether partial current periods are shown and how prior periods are aligned. Reference results should cover month boundary, year boundary, leap day where relevant, and late-arriving facts.
| Change | Compatibility class | Release action | Consumer evidence |
|---|---|---|---|
| Add optional documented dimension | Usually compatible | Add tests and announce | Existing queries unchanged |
| Rename display label only | Compatible if identifier stable | Update documentation | No query contract change |
| Change default filter | Breaking meaning | Create new version | Old/new population diff |
| Change entity or join path | Breaking calculation | Parallel metric versions | Grain and fanout comparison |
| Correct source defect | Operational correction | Incident and restatement notice | Affected periods and delta |
Test definitions at three layers
First, test source and dbt model invariants: keys, accepted values, relationships, freshness, and known exclusions. Second, test the semantic graph: valid entities, unambiguous joins, supported dimensions, and compilation. Third, test metric outcomes against small deterministic fixtures and production reconciliations. Include zero denominator, null measure, duplicate key, late event, missing dimension, and period-boundary cases. A compile-only check proves structure, not meaning.
Store reference queries and expected results in version control. Compare a candidate metric to the current production version over representative periods and segments. Explain differences by source correction, intentional contract change, or defect. Set tolerances only where numeric behavior truly permits them; exact counts should not receive a broad percentage tolerance. Run consumer smoke tests for the interfaces that matter, including filters and supported dimensions.
Version by semantic compatibility
Keep a stable identifier for compatible implementation changes, such as a performance rewrite that preserves results. Introduce a new metric name or version when business meaning changes. Link versions through metadata, state the replacement, and give a migration deadline. Do not repoint the old identifier to new logic on the assumption that corrected meaning excuses surprise. Historical consumers may need the old definition to reproduce a prior decision.
Use a pull-request checklist that classifies impact and lists dependent dashboards, saved queries, APIs, and owners. Run old and new versions in parallel. Publish overall and segmented deltas, especially where changes affect commissions, targets, customer entitlements, or external reporting. Deprecation begins only after the new version is queryable and documented. Removal follows evidence that required consumers migrated or received an approved exception.
Operate metrics after deployment
Monitor query success, latency, warehouse cost, freshness, dimension use, result anomalies, deprecated-version calls, and owner validity. A metric can be logically correct but operationally unusable if common groupings time out. Optimize semantic models, pre-aggregate where appropriate, and limit explosive dimensions without changing contract meaning. Return freshness and metric version to consumers so an incident can be distinguished from a legitimate definition release.
Schedule owner review for critical metrics. Confirm purpose, calculation, data sources, access class, consumers, and current limitations. Retire abandoned metrics through the same deprecation path rather than accumulating indistinguishable names. Keep change history and prior definitions long enough to reproduce governed reports. Treat disagreements as product feedback: the contract may need clearer variants rather than one overloaded metric.
Key takeaways
- Define decision, grain, population, time, unit, and ownership before implementing YAML.
- Prove entity cardinality and join paths instead of using them merely to make queries possible.
- Specify dimension history, calendars, nulls, and non-additive behavior.
- Test source invariants, semantic graph validity, and reference outcomes separately.
- Create a new version for changes in meaning, even when schemas still compile.
- Monitor freshness, performance, cost, consumer use, and deprecation after release.
Frequently asked questions
Is a dbt model contract the same as a metric contract?
No. A model contract governs the shape of a dbt model. A metric contract governs business calculation, grain, entities, dimensions, time, filters, ownership, and change behavior. The metric relies on model stability but adds semantic obligations.
When does a metric need a new version?
Create one when a reasonable consumer could receive a different business answer for the same request because grain, population, time, join path, formula, or null behavior changed. Pure performance work that preserves reference results can retain the version.
Who approves a metric definition?
The business decision owner approves meaning, the analytics engineer approves implementability and evidence, and data owners approve source and access assumptions. Critical cross-domain metrics may also need finance, risk, or governance review.
Conclusion
dbt and MetricFlow provide powerful primitives for centrally defined metrics. Versioned contracts supply the discipline that makes those primitives dependable interfaces. When grain, entities, dimensions, time, examples, ownership, tests, and migration rules are explicit, teams can reuse a calculation widely while retaining the ability to explain old results and improve future definitions without silent breakage.