dbt Metrics Layer
The dbt Metrics Layer (also called the dbt Semantic Layer) lets you define business metrics once inside your dbt project and query them consistently from any connected BI tool. Instead of each analyst or dashboard rebuilding "monthly revenue" with slightly different logic, you define it once in dbt and every tool reads the same definition.
The Problem Without a Metrics Layer
Revenue defined in Tableau: SUM(amount) WHERE status = 'completed' Revenue defined in Looker: SUM(amount) WHERE status = 'completed' AND refunded = false Revenue defined in Excel: SUM(amount) WHERE status = 'completed' AND test_order = false Result: Finance sees $10.2M in Tableau Sales sees $9.8M in Looker CEO sees $10.0M in the Excel report Everyone argues about which number is correct
The Metrics Layer solves this by making "revenue" a single definition that every tool reads from dbt.
MetricFlow: The Engine Behind the Metrics Layer
dbt uses MetricFlow to power the Semantic Layer. MetricFlow reads your metric definitions and generates the SQL needed to compute each metric dynamically for any time granularity or dimension combination requested.
Semantic Models
Before defining metrics, you define semantic models — descriptions of your tables that tell MetricFlow about entities, dimensions, and measures.
# models/marts/semantic_models.yml
semantic_models:
- name: orders
model: ref('fct_orders')
description: "Order fact table"
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
- name: status
type: categorical
- name: region
type: categorical
measures:
- name: order_count
agg: count
expr: order_id
- name: revenue
agg: sum
expr: amount_dollars
- name: average_order_value
agg: average
expr: amount_dollars
Defining Metrics
With semantic models in place, define metrics on top of them:
# models/marts/metrics.yml
metrics:
- name: total_revenue
label: "Total Revenue"
type: simple
type_params:
measure: revenue
description: "Sum of all completed order amounts in USD"
filter: "{{ Dimension('order__status') }} = 'completed'"
- name: monthly_active_customers
label: "Monthly Active Customers"
type: count_distinct
type_params:
measure: customer_id
description: "Count of unique customers who placed an order"
- name: revenue_growth_mom
label: "Revenue Growth MoM"
type: derived
type_params:
expr: (revenue - lag_revenue) / lag_revenue
metrics:
- name: total_revenue
alias: revenue
- name: total_revenue
alias: lag_revenue
offset_window: 1 month
Metric Types
Type Description ---------- ----------- simple Single aggregation on a measure (sum, count, avg, min, max) ratio One measure divided by another derived Custom expression combining multiple metrics cumulative Running total over a time window count_distinct Count of unique values
Querying Metrics with the dbt CLI
# Query a metric from the terminal dbt sl query \ --metrics total_revenue \ --group-by metric_time__month \ --order-by metric_time__month # Output: metric_time__month | total_revenue -------------------|--------------- 2025-01 | 1250000.00 2025-02 | 1380000.00 2025-03 | 1195000.00
Querying Metrics with Dimensions
dbt sl query \ --metrics total_revenue \ --group-by metric_time__month,region \ --where "region = 'North America'" \ --order-by metric_time__month # Output: metric_time__month | region | total_revenue -------------------|---------------|--------------- 2025-01 | North America | 750000.00 2025-02 | North America | 820000.00
BI Tool Integration
The dbt Semantic Layer integrates with BI tools via JDBC or a REST API. Supported integrations include:
- Tableau
- Looker
- Hex
- Mode
- Google Sheets
- Excel
Each BI tool reads your metric definitions from dbt and lets users query them without writing SQL. Users select a metric, choose a time grain and dimensions, and the BI tool sends the request to MetricFlow which generates and runs the SQL.
Benefits of a Centralised Metrics Layer
Benefit Result ------------------------ ------- Single metric definition Consistent numbers across all tools Business logic in dbt Versioned and tested like any other model No SQL in BI tools Analysts work with metric names, not SQL Dynamic time grains One definition serves daily, weekly, monthly Cross-tool consistency Tableau and Excel show the same number
Requirements
The dbt Semantic Layer requires dbt Cloud on the Team or Enterprise plan. MetricFlow is available in dbt Core for local development and testing, but BI tool integrations require dbt Cloud.
