MetricFlow Configuration Guide
What MetricFlow does
MetricFlow is a semantic layer framework for dbt that defines metrics once so every consumer gets the same calculation. When you define "revenue" in MetricFlow, every dashboard, ad hoc query, and downstream model that queries "revenue" uses the same formula. The definition is a contract -- it eliminates the "which revenue?" problem where different reports calculate the same metric differently.
Metric types
Simple metrics calculate a single aggregation over a measure. Revenue as the sum of order amounts. Average order value as the mean of order amounts. These are the building blocks.
Derived metrics combine other metrics with arithmetic. Profit margin as (revenue - cost) / revenue. Derived metrics reference other metric definitions, not raw columns -- if the underlying metric definition changes, the derived metric updates automatically.
Cumulative metrics aggregate over a rolling or unbounded time window. Year-to-date revenue. 30-day rolling average. These metrics require a time dimension and a grain specification.
Defining a metric
Metrics are defined in your schema.yml file alongside your dbt models. Here is an annotated example:
semantic_models:
- name: orders
defaults:
agg_time_dimension: order_date
model: ref('fct_orders')
entities:
- name: order_id
type: primary
- name: customer_id
type: foreign
dimensions:
- name: order_date
type: time
type_params:
time_granularity: day
- name: order_status
type: categorical
measures:
- name: order_total
agg: sum
expr: order_amount
- name: order_count
agg: count
expr: order_id
metrics:
- name: revenue
description: "Total revenue from completed orders"
type: simple
type_params:
measure: order_total
filter:
- "{{ Dimension('order_status') }} = 'completed'"
- name: average_order_value
description: "Average value per completed order"
type: derived
type_params:
expr: revenue / order_count
metrics:
- name: revenue
- name: order_count
Key elements:
- Semantic model defines the source table, its entities (keys), dimensions (grouping columns), and measures (aggregatable columns)
- Metrics reference measures and apply filters, creating a single authoritative calculation
- Filters are applied at the metric level, not the query level -- every consumer gets the filtered result
Querying metrics
Once defined, metrics are queried via the mf query command or through the dbt Semantic Layer API:
mf query --metrics revenue --group-by order_date__month
This returns the metric value grouped by month, using the definition you specified. The formula, the filter, the aggregation -- all locked in. The consumer specifies what to group by and what time range to query, but never redefines how the metric is calculated.
Verification
After defining a metric:
- Query the metric via
mf queryfor a specific time period and grouping - Calculate the same value by hand from the raw data using SQL -- apply the same formula, the same filters, the same grain
- Compare the results -- they should match exactly. If they don't, the metric definition encodes a different calculation than you intended
This verification step is critical. A metric definition that compiles and returns a number is not the same as a metric definition that returns the right number. The formula must match the business intent, not just pass syntax validation.
Common pitfalls
- Formula that compiles but calculates wrong. The metric definition is valid YAML, the query returns a number, but the number doesn't match what the business means. This happens when filters exclude or include the wrong records, or when the aggregation type is wrong (sum vs count, mean vs median).
- Missing filters that change the denominator. An "average order value" that doesn't filter out cancelled orders includes zeros in the denominator, producing a lower average than the business expects.
- Name collisions with existing metrics. If two metrics have the same name but different calculations, one silently overrides the other. Always check that a metric name doesn't already exist before defining it.
- Time grain mismatches. A metric defined at daily grain queried at monthly grain may produce unexpected results if the aggregation doesn't compose correctly (e.g., averaging daily averages is not the same as the monthly average).
- Derived metrics referencing stale components. If a derived metric references another metric that was redefined, the derived metric's behavior changes without any direct edit to its definition.