The Problem: Metric Definitions Scattered Across Tools
Without a semantic layer, 'revenue' often gets defined three different ways: once in a Looker LookML model, once in a hand-written Tableau calculated field, and once in an analyst's ad hoc SQL query — and each definition can subtly diverge, whether that's including or excluding refunds, or using a different date field for revenue recognition. The dbt Semantic Layer solves this by centralizing metric logic as code in the dbt project itself, defined on top of your governed marts models, so 'revenue' is defined exactly once and every downstream tool — Tableau, Hex, Google Sheets, or a Python notebook — queries that same governed definition instead of reimplementing it.
Cricket analogy: This is like a cricket board finally publishing one official definition of a bowler's 'economy rate' formula, after each broadcaster had been quietly computing it slightly differently, some including wides and no-balls, some not.
Semantic Models and Metrics
The Semantic Layer is built on two YAML concepts on top of your existing marts models. A semantic_model declares which mart it's built on, what its entities (join keys like customer_id), dimensions (attributes to group by, like plan_name or a date), and measures (raw aggregations like sum of amount) are. A metric then references one or more measures and combines them into a named, queryable business definition — a simple type: simple metric wraps a single measure, while a type: ratio metric divides one measure by another (like refund amount over gross revenue), and a type: derived metric combines other metrics with an expression. MetricFlow, the engine underneath, compiles a metric query plus any requested dimensions and time grain into optimized SQL against your warehouse at query time.
Cricket analogy: This is like defining 'strike rate' as a metric built on the underlying 'runs scored' and 'balls faced' measures pulled from the raw ball-by-ball semantic model, so any broadcaster querying strike rate by player or by innings gets the identical calculation.
# models/marts/finance/_finance__semantic_models.yml
semantic_models:
- name: sm_orders
model: ref('fct_orders')
entities:
- name: order
type: primary
expr: order_id
- name: customer
type: foreign
expr: customer_id
dimensions:
- name: order_date
type: time
type_params:
time_granularity: day
measures:
- name: order_total
agg: sum
expr: amount_usd
metrics:
- name: revenue
type: simple
type_params:
measure: order_total
- name: refund_rate
type: ratio
type_params:
numerator: refund_total
denominator: order_totalOnce metrics are defined, you query them with the dbt CLI via dbt sl query --metrics revenue --group-by metric_time__month, or connect a downstream BI tool through the Semantic Layer API/JDBC driver so the tool sends metric queries instead of raw SQL — the governed definition lives in one place regardless of which tool asks for it.
Semantic models must be built on top of already-modeled marts, not raw sources — the Semantic Layer is a governance layer over your existing dbt DAG, not a replacement for staging/intermediate/marts modeling. Skipping straight from source() to a semantic_model reintroduces the same inconsistency problem the Semantic Layer is meant to eliminate.
- The Semantic Layer centralizes metric definitions as code so every downstream tool queries the same governed logic.
- semantic_models declare entities (join keys), dimensions (group-by attributes), and measures (raw aggregations) on top of a mart.
- Metrics combine measures into named business definitions: simple, ratio, and derived are the core metric types.
- MetricFlow compiles metric + dimension + time-grain requests into optimized SQL at query time.
- Metrics are queryable via the dbt CLI (
dbt sl query) or via connected BI tools through the Semantic Layer API. - Semantic models must sit on top of governed marts, never directly on raw sources.
- The core value is consistency: 'revenue' means the same thing everywhere it's queried, once defined.
Practice what you learned
1. What problem does the dbt Semantic Layer primarily solve?
2. In a semantic_model, what does a 'measure' represent?
3. What does a type: ratio metric do?
4. What engine compiles metric and dimension requests into SQL at query time?
5. Where should a semantic_model be built on top of?
Was this page helpful?
You May Also Like
Staging, Intermediate, and Marts Layers
dbt's layered modeling pattern moves raw source data through staging (cleaning), intermediate (business logic building blocks), and marts (business-facing fact/dim tables).
Incremental Models In-Depth
Incremental models process only new or changed rows on subsequent runs instead of rebuilding the full table, using is_incremental() and configurable strategies to control merge behavior.
Snapshots
dbt snapshots implement Type 2 slowly changing dimensions, capturing row-level changes over time so you can query what a record looked like at any past point.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
ProgrammingPowerShell Study Notes
Programming · 30 topics