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.
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.
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
Treat metric semantics as versioned contracts with deterministic hashes.
Deprecate ambiguous/breaking definitions instead of mutating them in place.
Attach golden-result, lineage, security, and edge-case tests to each metric.
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
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
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
- Register the new version/metric with owner approval.
- Run historical and edge-case comparisons against the old definition.
- Enumerate downstream consumers using lineage/query telemetry.
- Publish a migration window and changed-result examples.
- Dual-run critical reports; require sign-off.
- Mark old version deprecated but still reproducible.
- 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
- When is a metric change breaking?
- What does a spec hash prove and not prove?
- Why retain a deprecated definition during migration?
- Which test catches a wrong retention denominator?
- 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
- Kimball Group — Conformed DimensionsBackground for shared dimensional meaning across analytical consumers and processes.
- Kimball Group — Fact TablesGrain-first fact-table guidance underlying safe metric aggregation.
- dbt — MetricFlow overviewCurrent official example of a semantic metric engine. It is a non-prerequisite product reference, not the course's semantic source of truth.
- dbt — Semantic LayerCurrent official example of centrally defined metrics consumed across tools; exact capabilities and syntax are product-specific.
- PostgreSQL — Row Security PoliciesOfficial engine-specific reference for row-level security. The mandatory local lab simulates entitlement filtering with joins instead of claiming SQLite has equivalent native RLS.
- SQLite — SELECTOfficial semantics for the deterministic local SQL examples.
- Python — sqlite3Standard-library interface used by the no-cost local lab.
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.