> ## Documentation Index
> Fetch the complete documentation index at: https://lightdash-mintlify-4096358d.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# dbt MetricFlow metrics

> Connect Lightdash to your dbt MetricFlow semantic layer metrics

If your dbt project defines metrics using [MetricFlow](https://docs.getdbt.com/docs/build/about-metricflow) (dbt's semantic layer), the Lightdash CLI can translate them into Lightdash metrics automatically when you deploy. You keep a single source of truth for metric definitions in MetricFlow format, and Lightdash reads them directly from your compiled dbt project. You don't need a dbt Cloud subscription or the dbt Semantic Layer API, and you don't need to duplicate the definitions.

## How it works

When you run `lightdash deploy` (or `lightdash compile` / `lightdash preview`), the CLI reads your project's compiled `manifest.json`, which contains everything MetricFlow knows about your project: the `semantic_models` (entities, dimensions, measures) and the `metrics` defined on top of them.

These metrics can then be used everywhere Lightdash metrics work (charts, dashboards, the API, AI agents).

```bash theme={null}
dbt parse                # or dbt compile — writes target/manifest.json
lightdash deploy         # translates MetricFlow metrics as part of the deploy
```

<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.
</Info>

### Use the latest MetricFlow spec

Lightdash supports the latest and legacy spec, though it's recommended to use the latest spec.

* **Legacy spec** (dbt Core 1.6+): top-level `semantic_models:` and `metrics:` blocks with `type_params`.
* [**Latest spec**](https://docs.getdbt.com/docs/build/latest-metrics-spec) (dbt Fusion engine, dbt platform, dbt Core 1.12+): `semantic_model:` enabled inline on the model, with entities/dimensions on columns and metrics using top-level `agg` / `expr` keys.

## Supported features

`simple` metrics, and measures flagged `create_metric: true`, translate into Lightdash:

| MetricFlow              | Lightdash metric type                         |
| ----------------------- | --------------------------------------------- |
| `agg: sum`              | `sum`                                         |
| `agg: count`            | `count`                                       |
| `agg: count_distinct`   | `count_distinct`                              |
| `agg: average`          | `average`                                     |
| `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` |

Also carried over:

* **Measure** `expr`: bare column references and SQL expressions both become the metric's SQL.
* **Labels and descriptions**: from the metric, falling back to the measure's.

### Filters

Metric-level and measure-level `filter:` templates translate when every reference is a `{{ Dimension('entity__dimension') }}` that resolves on the metric's own semantic model. The filter is compiled into the metric SQL:

```yaml theme={null}
- name: completed_revenue
  type: simple
  type_params:
    measure: total_revenue
  filter: |
    {{ Dimension('order__status') }} = 'completed'
```

becomes a Lightdash `sum` metric with SQL `CASE WHEN ("orders".status = 'completed') THEN ("orders".amount) END`. The dimension's `expr` is used when it isn't a plain column.

Filters referencing dimensions on **other** semantic models, or using other template functions (`TimeDimension()`, `Entity()`, `Metric()`), are skipped with a warning.

### Ratio metrics

`ratio` metrics translate to a non-aggregate Lightdash `number` metric dividing the two input metrics, when the numerator and denominator both live on the **same model**:

```yaml theme={null}
- name: revenue_per_order
  type: ratio
  type_params:
    numerator: total_revenue
    denominator: order_count
```

becomes `(${total_revenue} * 1.0) / NULLIF(${order_count}, 0)` — the `* 1.0` avoids integer division on warehouses that truncate, and `NULLIF` avoids division-by-zero errors.

Filtered inputs work too: a numerator with its own `filter:` (e.g. completion rate = completed orders ÷ all orders) compiles the filter into a hidden helper metric that the visible ratio references. A ratio-level `filter:` applies to both inputs.

### Derived metrics

`derived` metrics translate to a `number` metric with the expression rewritten over the input metrics (aliases supported), again when all inputs live on the same model:

```yaml theme={null}
- name: revenue_per_customer
  type: derived
  type_params:
    expr: total_revenue / unique_customers
    metrics:
      - name: total_revenue
      - name: unique_customers
```

becomes `${total_revenue} / ${unique_customers}`. Inputs using `offset_window` or `offset_to_grain` (time-shifted metrics) are skipped with a warning.

<Info>
  **Why same-model only?** MetricFlow computes each input metric in its own aggregation subquery — even across unrelated tables — and joins the already-aggregated results. Lightdash compiles one query per explore, so ratio/derived metrics translate faithfully only when all inputs resolve to metrics on the same dbt model. Cross-model inputs are skipped with a warning naming the models involved.
</Info>

## What's not supported yet

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

| MetricFlow feature                                               | Notes                                                                 |
| ---------------------------------------------------------------- | --------------------------------------------------------------------- |
| `cumulative` metrics                                             | require time-spine semantics                                          |
| `conversion` metrics                                             | require entity-journey semantics                                      |
| Cross-model `ratio` / `derived` inputs                           | inputs must resolve to metrics on the same model (see above)          |
| `offset_window` / `offset_to_grain` inputs                       | time-shifted inputs have no Lightdash metric equivalent               |
| Cross-model or non-`Dimension()` `filter:` templates             | only same-model `{{ Dimension('entity__dim') }}` references translate |
| `percentile_type: discrete`                                      | Lightdash percentiles always compile to `PERCENTILE_CONT`             |
| `join_to_timespine`, `fill_nulls_with`, `non_additive_dimension` | no equivalents                                                        |

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)).
* **Dimensions and `agg_time_dimension`.** Lightdash generates dimensions from your model's real columns, so all of your columns are already available as dimensions, and metrics can be grouped by any of them — the MetricFlow dimension definitions aren't needed. (Dimension `expr` is honored when resolving filter references.)

## Example

A complete working example (both specs, with a reproducible test) lives in the Lightdash repo under [`examples/metricflow-demo`](https://github.com/lightdash/lightdash/tree/main/examples/metricflow-demo) — it exercises every supported shape, including filtered, ratio, derived, and `sum_boolean` metrics. The short version, in the legacy spec:

```yaml theme={null}
semantic_models:
  - name: orders
    model: ref('orders')
    defaults:
      agg_time_dimension: ordered_at
    entities:
      - name: order
        type: primary
        expr: order_id
    dimensions:
      - name: ordered_at
        type: time
        type_params:
          time_granularity: day
    measures:
      - name: total_revenue
        agg: sum
        expr: amount
      # create_metric: true auto-creates a metric — also translated
      - name: unique_customers
        agg: count_distinct
        expr: customer_id
        create_metric: true

metrics:
  - name: total_revenue
    label: Total revenue
    type: simple
    type_params:
      measure: total_revenue
```

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.
