Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 51 additions & 7 deletions references/integrations/dbt-metricflow.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,13 @@ dbt parse # or dbt compile — writes target/manifest.json
lightdash deploy # translates MetricFlow metrics as part of the deploy
```

### Requirements

- **dbt Core 1.6 or later** (manifest schema `v10`, the first version to include MetricFlow's semantic layer). The legacy metrics format used by pre-1.6 dbt (`calculation_method` / `expression` / `time_grains`) is no longer read.
- **The Lightdash CLI.** Translation happens in `lightdash compile`, `lightdash preview`, and `lightdash deploy`. Server-side jobs (scheduled runs from a connected Git repo) don't currently translate MetricFlow metrics — for now, deploy from the CLI.

<Info>
If you define a metric with the same name in both MetricFlow and your model's `meta.metrics`, the `meta.metrics` (Lightdash YAML) definition will take precedence.
If you define a metric with the same name in both MetricFlow and your model's `meta.metrics`, the `meta.metrics` (Lightdash YAML) definition will take precedence — so you can always override a translated metric by hand.
</Info>

### Use the latest MetricFlow spec
Expand All @@ -42,27 +47,42 @@ Lightdash supports the latest and legacy spec, though it's recommended to use th
| `agg: median` | `median` |
| `agg: min` / `agg: max` | `min` / `max` |
| `agg: percentile` | `percentile` |
| `agg: sum_boolean` | `sum` over `CASE WHEN <bool> THEN 1 ELSE 0 END` |
| Metric or measure `filter:` (same-model `Dimension()` refs) | filter compiled into the metric SQL as `CASE WHEN <condition> THEN <expr> END` |
| `ratio` metrics (inputs on the same dbt model) | `number` metric: `(${numerator} * 1.0) / NULLIF(${denominator}, 0)` |
| `derived` metrics (inputs on the same dbt model, no offsets) | `number` metric with the `expr` rewritten over `${metric}` references |

Also carried over:

- **Measure** `expr`: bare column references and SQL expressions both become the metric's SQL.
- **Measure** `expr`: bare column references become the metric's SQL, qualified with `${TABLE}` (for example, `expr: amount` becomes `sql: ${TABLE}.amount`). Full SQL expressions are used verbatim.
- **Labels and descriptions**: from the metric, falling back to the measure's.
- **Percentile value**: MetricFlow's legacy spec authors percentile as a `0–1` fraction (`percentile: 0.95`) and the latest spec authors it as `0–100` (`percentile: 95`). Both are normalized to Lightdash's `0–100` scale automatically.
- **`config.meta.hidden` and `config.meta.group_label`**: read from the metric first, falling back to the measure. Use them to hide translated helper metrics from the explore sidebar or [group them](/references/metrics#groups) alongside your other Lightdash metrics. Unknown keys under `config.meta` are ignored.

### Notes on filters, ratio, and derived metrics

- **Filters** translate when every `{{ Dimension('entity__dim') }}` reference resolves on the metric's own semantic model. Cross-model dimension references, and other template functions (`TimeDimension()`, `Entity()`, `Metric()`), skip the metric with a warning.
- **Ratio and derived inputs** must all resolve to metrics on the same dbt model. In MetricFlow, inputs can come from any semantic model because each input is aggregated in its own subquery; Lightdash compiles a single query per explore, so cross-model inputs are skipped with a warning. Join the relevant models in a Lightdash explore and author a `number` metric by hand if you need that today.
- **Filtered inputs** to a ratio or derived metric (for example, a ratio whose numerator has its own `filter:`) compile the filter into a hidden helper metric that the visible metric references.
- **Time-offset inputs** to a derived metric (`offset_window` or `offset_to_grain`) are skipped with a warning.

## What's not supported yet

These are skipped with a warning on deploy (details under `--verbose`):

| MetricFlow feature | Notes |
| --- | --- |
| `ratio` metrics | numerator/denominator over other metrics |
| `derived` metrics | expressions over other metrics |
| `cumulative` metrics | require time-spine semantics |
| `conversion` metrics | require entity-journey semantics |
| Metric or measure `filter:` | MetricFlow where-filter templates (e.g. `{{ Dimension('order__status') }} = 'completed'`) don't map to Lightdash metric filters |
| `agg: sum_boolean` | no Lightdash equivalent |
| Cross-model `ratio` / `derived` inputs | inputs must all resolve on the same dbt model — see the notes above |
| Derived-metric `offset_window` / `offset_to_grain` | time-offset inputs aren't translated |
| `filter:` templates that aren't same-model `Dimension()` refs | cross-model dimensions and `TimeDimension()` / `Entity()` / `Metric()` templates don't map to Lightdash metric filters |
| `agg: percentile` without a numeric `percentile` value | skipped rather than defaulted — set `type_params.measure.agg_params.percentile` (legacy) or `agg_params.percentile` (latest) |
| `percentile_type: discrete` | Lightdash percentiles always compile to `PERCENTILE_CONT` |
| `join_to_timespine`, `fill_nulls_with`, `non_additive_dimension` | no equivalents |

Cumulative and conversion metric translation, cross-model ratio/derived inputs, and server-side translation from a connected Git repo are on the roadmap.

And these parts of the semantic model are currently skipped:

- **Entities / joins.** MetricFlow joins semantic models implicitly at query time through shared entity keys. Lightdash joins are explicit and authored per-explore ([joining tables](/references/joins)).
Expand All @@ -87,10 +107,15 @@ semantic_models:
type: time
type_params:
time_granularity: day
- name: status
type: categorical
measures:
- name: total_revenue
agg: sum
expr: amount
- name: order_count
agg: count
expr: order_id
# create_metric: true auto-creates a metric — also translated
- name: unique_customers
agg: count_distinct
Expand All @@ -103,6 +128,25 @@ metrics:
type: simple
type_params:
measure: total_revenue
# config.meta carries over to the translated Lightdash metric
config:
meta:
group_label: Order metrics
# Same-model filter → CASE WHEN in the metric SQL
- name: completed_revenue
label: Completed revenue
type: simple
type_params:
measure: total_revenue
filter: |
{{ Dimension('order__status') }} = 'completed'
# Same-model ratio → Lightdash `number` metric
- name: revenue_per_order
label: Revenue per order
type: ratio
type_params:
numerator: total_revenue
denominator: order_count
```

Deploying this project gives the `orders` explore two metrics, `Total revenue` (`SUM("orders".amount)`) and `unique_customers` (`COUNT(DISTINCT "orders".customer_id)`), with no Lightdash-specific YAML.
Deploying this project produces four metrics on the `orders` explore: `total_revenue` (`sum` on `${TABLE}.amount`, grouped under "Order metrics"), `unique_customers` (`count_distinct` on `${TABLE}.customer_id`, from the `create_metric: true` measure), `completed_revenue` (a `sum` over `CASE WHEN ${TABLE}.status = 'completed' THEN ${TABLE}.amount END`), and `revenue_per_order` (a `number` metric of `(${total_revenue} * 1.0) / NULLIF(${order_count}, 0)`) — all with no Lightdash-specific YAML.
4 changes: 4 additions & 0 deletions references/metrics.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ To add a metric to Lightdash using the `meta` tag, you define it in your dbt pro

Once you've got the hang of what these metrics look like, read more about the [metric types you can use below.](#metric-types)

<Info>
Already defining metrics with [dbt MetricFlow](https://docs.getdbt.com/docs/build/about-metricflow)? The Lightdash CLI can translate the supported subset of MetricFlow metrics into Lightdash metrics on `lightdash deploy`, so you don't have to duplicate the definitions in `meta.metrics`. See [dbt MetricFlow metrics](/references/integrations/dbt-metricflow).
</Info>

### 2. Using the model `meta` tag

Sometimes a metric references multiple columns, in these cases you can define the metric at the model level:
Expand Down