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

Central Metric Definitions, Measures vs Metrics, Filters, Time Windows, Currency/Unit Semantics, and Ownership

Define measures and metrics centrally with explicit filters, date windows, units, currency, owners, zero-denominator behavior, and executable golden results rather than dashboard-local assumptions.

Intermediate → Advanced150–185 minutesMetric specification + edge-case labUSD-only gate · inclusive UTC date windowsLast 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

Write complete metric specifications including aggregation, filters, time, currency/units, ownership, and edge behavior.

02

Distinguish a raw/additive measure from a business metric evaluated in context.

03

Reject mixed-currency aggregation without an explicit conversion policy.

04

Test active-customer and retention boundaries, including a zero prior population.

1. Start with the decision, not the arithmetic

Finance asks “how much paid gross revenue did we book?” Growth asks “how many distinct customers bought during this interval?” Retention asks “what fraction of last period’s active customers returned?” The formulas look small, but each depends on a source event, population, time window, and unit. A central definition is useful only if it records all of those choices.

Calling amount_cents a metric is incomplete: it is a row-level measure stored at the order-line grain. SUM(amount_cents) is an aggregation, but it still becomes a business metric only after status, currency, date semantics, allowed grouping dimensions, ownership, and version are fixed.

2. Required fields in a metric specification

Field AtlasMart example Failure if omitted
Name/version gross_revenue_usd.v1 Meaning changes in place
Population/filter status='paid' Pending/cancelled events leak in
Measure/aggregation SUM(amount_cents) Column is mistaken for a final metric
Time dimension/window order_date, inclusive closed range, UTC Boundary events move or disappear
Unit/currency USD cents → USD display Incomparable values are added
Owner finance-analytics / growth-analytics No authority for changes/incidents
Zero/null behavior retention denominator 0 → NULL Undefined state becomes misleading 0%
Security inheritance apply entitlement before aggregation Restricted rows leak through aggregate

3. Time windows are semantics, not UI defaults

The golden active-customer window is 2026-09-20 through 2026-09-22, inclusive, in the warehouse’s UTC date semantics. It contains six paid lines but only four distinct customers. The prior retention window is Sep 18–19 with two active customers; the current window has four; one customer appears in both; therefore retention is 1/2 = 50%.

governed retention SQL
WITH prior AS (  SELECT DISTINCT customer_id  FROM fact_sales  WHERE status='paid'    AND order_date BETWEEN :prior_start AND :prior_end), current AS (  SELECT DISTINCT customer_id  FROM fact_sales  WHERE status='paid'    AND order_date BETWEEN :current_start AND :current_end), counts AS (  SELECT    (SELECT COUNT(*) FROM prior) AS prior_n,    (SELECT COUNT(*) FROM current) AS current_n,    (SELECT COUNT(*) FROM prior p JOIN current c USING(customer_id)) AS retained_n)SELECT prior_n,current_n,retained_n,       CASE WHEN prior_n=0 THEN NULL            ELSE retained_n*1.0/prior_n END AS retention_rateFROM counts;
Wrong denominator

Dividing the same one retained customer by the four current-period active customers yields 25%. That query is mathematically valid but answers a different question. The denominator belongs in the metric specification.

4. Currency and units: reject ambiguity before conversion

All accepted current sales rows are USD cents. The lab copies them into a temporary probe and adds one EUR row. The gate sees two currencies and returns BLOCK. This is deliberate: a semantic layer must not invent an exchange rate or treat 1,000 EUR cents as 1,000 USD cents.

currency gate
SELECT COUNT(DISTINCT currency_code) AS currenciesFROM currency_probeWHERE status='paid';-- if currencies > 1 and no governed FX policy exists: BLOCK

A future FX-enabled metric would need an authoritative rate source, rate type (spot/close/average), effective time, source/reporting currency, rounding, missing-rate policy, restatement behavior, and version. Those are business/accounting rules, not merely SQL casts.

5. Measures, metrics, and derived metrics

Stored measure: amount_cents at one order line. Aggregated measure: SUM(amount_cents) in a query group. Metric: gross_revenue_usd.v1 binds that sum to paid USD rows and UTC order-date context. Derived metric: retention computes a ratio of two governed customer sets. Distinct counts and ratios are non-additive: precomputing them requires compatible set/state semantics, not blind summation.

6. Ownership is part of correctness

Finance Analytics owns gross revenue because it decides whether future returns, taxes, discounts, or restatements should alter the definition. Growth Analytics owns active-customer and retention semantics. Engineering implements and tests the contract but should not silently choose the business denominator. A change request therefore has an accountable reviewer and consumer migration plan.

Ownership also covers incidents: who responds when the source is late, when an accelerator is stale, when a consumer requests an unsupported currency, or when a metric version is deprecated.

7. Rerun and test behavior

Metric evaluation is deterministic for the same certified warehouse state, parameters, security principal, and metric version. The lab writes deterministic specification hashes; re-running setup recreates the same hashes and golden results. If a spec changes, the hash changes and compatibility must be revalidated. This is not distributed exactly-once execution; it is reproducible semantic evaluation over a fixed fixture.

generation metric hashes
gross_revenue_usd.v1  6be77e930e087257e5756fc2c9ccddd4293fed6a457d3a8c72badef65dad5e8aactive_customers.v1   1fb6a9bb4c820d321fe786b0809124fa279182c0f6a28e81db1194f37ada1eb0period_retention.v1   66e7840903abf5f871d39f72c35935d3d98cbadb8496480342f781777da3a962

8. Production judgment and bridge

Do not make every ad-hoc calculation a centrally certified metric. Central governance is justified when a definition is shared, decision-relevant, security-sensitive, audited, or expensive to duplicate incorrectly. Keep experimentation possible in sandboxes, but require promotion before a number is labeled certified.

Lesson 3 adds semantic relationships, drill paths, and security. These determine which dimensions a metric can safely use and which rows a principal may see before aggregation.

Knowledge check

Check your understanding

  1. Why is SUM(amount_cents) still not a complete revenue definition?
  2. Why is the retention denominator part of the contract?
  3. What should happen when a mixed currency appears without FX policy?
  4. Why is owner metadata operationally useful?
  5. When should a calculation remain exploratory rather than certified?
Review the answers

1. It omits population, time, currency, version, owner, security, and edge behavior.

2. Changing it changes the business question even if the numerator is unchanged.

3. Block/reject the ambiguous aggregation until governed conversion semantics exist.

4. It identifies the authority for definition changes and incident response.

5. When it is provisional, local to analysis, or not yet reviewed/tested for shared decision use.

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.