Chapter 20 · Semantic Layers, Metrics, Dimensions, Measures, and BI Contracts

Metric Versioning, Deprecation, Tests, Documentation, and Preventing Dashboard-Specific Business Logic

Version metric semantics as contracts, deprecate rather than mutate breaking definitions, attach tests and documentation, and migrate consumers away from dashboard-specific business logic safely.

Intermediate → Advanced135–170 minutesVersioning/deprecation + golden testsDeterministic spec hashes · consumer migrationLast reviewed: September 2026
Continuity and explicit semantic layer addition

Chapter 20 begins from the Chapter 19 post-refresh warehouse truth at source sequence 207: 10 current paid lines, 8 orders, 12 units, 820 USD gross revenue, 495 USD cost, and 325 USD gross profit. The atomic fact grain remains one current paid order line. This chapter does not rewrite facts, SCD history, bridge allocations, physical layout, or the acceleration layer. It adds a governed semantic contract above those structures so consumers use the same metric definitions regardless of whether a query is served from atomic facts or an eligible accelerator.

Lab contract

Runtime: Python standard library plus SQLite; generation evidence used Python 3.13.5 and SQLite 3.46.1. Environment: local/in-process and synthetic, with no paid service. Source lineage: AtlasMart ERP orders/order lines plus governed warehouse facts and dimensions. Fact grain: one current sales order line. Time: governed metric windows use inclusive warehouse order_date boundaries in UTC; the lab does not infer user-local calendar dates. Currency: the governed revenue metric accepts USD rows only; mixed currencies are blocked until an explicit FX policy exists. Security: synthetic geography entitlements; row-level filtering is applied before aggregation. Acceleration: the Chapter 19 daily/product aggregate is a physical implementation option and must reconcile to semantic truth. Non-guarantee: the tiny compiler demonstrates contract mechanics, not a production BI semantic engine or universal SQL dialect.

Learning outcomes

01

Treat metric semantics as versioned contracts with deterministic hashes.

02

Deprecate ambiguous/breaking definitions instead of mutating them in place.

03

Attach golden-result, lineage, security, and edge-case tests to each metric.

04

Plan consumer migration and rollback when a semantic version changes.

1. Metric changes are API changes for data consumers

Once dashboards, finance extracts, notebooks, alerts, and applications depend on gross_revenue_usd.v1, its semantics are an interface. Changing paid-status treatment, currency conversion, date timezone, or return handling can change historical results even if the metric name stays the same. Therefore a semantic change is versioned and reviewed like a contract change.

The lab keeps an intentionally ambiguous revenue_legacy.v0 entry as deprecated evidence and points consumers to gross_revenue_usd.v1. It does not overwrite the legacy record and pretend the old dashboard always meant the new definition.

2. Registry state is observable

metric registry
active_customers.v1   | v1 | active     | growth-analytics  | replacement=NULLgross_revenue_usd.v1  | v1 | active     | finance-analytics | replacement=NULLperiod_retention.v1    | v1 | active     | growth-analytics  | replacement=NULLrevenue_legacy.v0      | v0 | deprecated | legacy-bi         | replacement=gross_revenue_usd.v1

Each active specification is serialized canonically and hashed. A hash is not a proof that the definition is correct; it is an identity for the exact reviewed bytes. When the specification changes, the hash changes, which forces compatibility tests for accelerators, adapters, golden results, and consumers.

3. Controlled failure: changing v1 in place

Wrong approach

Suppose Finance decides revenue should now subtract returns. Editing the formula behind gross_revenue_usd.v1 without changing version/name can silently rewrite every historical dashboard and invalidate cached aggregates. A consumer cannot reproduce yesterday’s number because “v1” no longer identifies one meaning.

Safer options depend on intent: create a separately named net_revenue_usd.v1 if it is a different business concept, or create gross_revenue_usd.v2 if the same named contract has an intentionally breaking definition. Keep v1 during a migration window, publish differences, identify consumers, and set a deprecation date.

4. Tests belong to the metric contract

Test AtlasMart evidence Failure caught
Golden result Revenue = 820 USD at seq 207 Filter/formula drift
Window boundary Current active Sep20–22 = 4 Inclusive/exclusive mismatch
Retention denominator 1 retained / 2 prior = 50% Wrong population
Zero denominator No prior actives → NULL Invented percentage
Currency USD+EUR probe → BLOCK Unit corruption
Security East revenue = 395 USD RLS bypass
Acceleration Base 820 = aggregate 820 Stale/incompatible physical route

5. Documentation is executable context, not a prose afterthought

A useful metric page records name/version, business question, source event, fact grain, formula, filters, dimensions, time semantics, currency/units, security inheritance, owner/steward, freshness/SLO, lineage, examples, known exclusions, golden tests, version history, deprecation status, and consumer migration notes. Generated SQL can be shown as evidence but should not replace the business definition.

Documentation must distinguish what the metric means from how the current engine computes it. That separation lets AtlasMart change from SQLite teaching harness to a cloud warehouse without silently changing semantics.

6. Consumer migration and deprecation

  1. Register the new version/metric with owner approval.
  2. Run historical and edge-case comparisons against the old definition.
  3. Enumerate downstream consumers using lineage/query telemetry.
  4. Publish a migration window and changed-result examples.
  5. Dual-run critical reports; require sign-off.
  6. Mark old version deprecated but still reproducible.
  7. Disable only after consumers migrate and rollback criteria are satisfied.

Urgent correctness/security fixes may require faster action, but the audit record should still preserve who approved the change and what historical outputs are affected.

7. Prevent dashboard-specific business logic

Dashboards may select dimensions, filters explicitly allowed by the contract, and visual calculations such as percentages of displayed total when clearly labeled. Core definitions such as “paid,” active-customer identity, retention denominator, currency conversion, or security must not be reimplemented independently in each workbook. CI can search semantic models/dashboard metadata for forbidden duplicate expressions where the tooling exposes them.

8. Production judgment and bridge

Versioning increases governance overhead, so use it for decision-relevant semantics rather than cosmetic changes. A formatting change from $820.00 to $820 need not create a new business metric version; changing the population or denominator does.

Lesson 5 combines the registry, compiler, golden tests, RLS, currency gate, acceleration cross-check, and lineage into one reproducible acceptance workflow.

Knowledge check

Check your understanding

  1. When is a metric change breaking?
  2. What does a spec hash prove and not prove?
  3. Why retain a deprecated definition during migration?
  4. Which test catches a wrong retention denominator?
  5. Why should semantic documentation separate meaning from engine SQL?
Review the answers

1. When the same request/context can produce materially different business meaning/result.

2. It identifies exact spec bytes; it does not prove business correctness.

3. Reproducibility, comparison, rollback, and controlled consumer migration.

4. The golden population/count test: retained=1, prior=2, result=50%.

5. Engines/tools can change while governed business semantics should remain stable.

Authoritative references

9. Lab cleanup/reset

The mandatory examples use only the deterministic local Chapter 20 fixture. Delete atlasmart_ch20_lab (or your configured local output directory) and rerun python ch20_lab.py to recreate a clean state. The script recreates the SQLite database and metric/report files; it does not create cloud resources or modify the academy repository.

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only Ethereum or ERC-20 compatible assets to this address.