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.

Leave a Comment

Your email address will not be published. Required fields are marked *