Skip to content

MetricFlow

MetricFlow is dbt's semantic-layer query engine. It lets Dataface ask for metrics and dimensions by name instead of embedding SQL in every board.

Use it when your dbt project already defines shared metrics and you want boards to reuse those definitions.


Why Use MetricFlow?

Traditionally, BI tools require you to write SQL queries for every chart, or model data specifically for the tool. This leads to: - Inconsistent metrics: "Revenue" might be calculated differently in two different charts. - Maintenance headaches: Changing a metric definition requires updating SQL in 20 different places. - Rigid querying: Hard to drill down or change time grains on the fly.

MetricFlow solves this by letting you define metrics once in your dbt project. Dataface then asks for "revenue by month," and MetricFlow generates the SQL.

Benefits

  1. Define metrics in dbt and reuse them in Dataface.
  2. Write shorter board YAML for standard metric queries.
  3. Change time grains or dimensions without rewriting SQL.
  4. Keep metric definitions consistent across boards.

How It Works

A metrics:/dimensions: query lowers to plain SQL at compile time: Dataface calls MetricFlow's own compiler (MetricFlowEngine.explain) against your dbt project's semantic manifest and gets back a finished SELECT statement. That SQL then runs through the query's dbt_profile source exactly like a hand-written SQL query — caching, variable substitution in the rest of the board, and the compile-time SQL guard all apply for free. There is no MetricFlow call at render or execute time, and no live connection to MetricFlow needed in production.

One consequence of compiling at build time: MetricFlow bakes filter literals directly into the generated SQL, so a metricflow query's shape (metrics, dimensions, time grain) can't react to a {{ variable }} at render time the way a sql: query can — see Filters and Variables below.

Install the optional extra to compile metricflow queries:

pip install dataface[metricflow]

1. Define Metrics in dbt

First, define metrics in your dbt project.

# dbt_project.yml or schema.yml
metrics:
  - name: total_revenue
    type: simple
    type_params:
      measure: revenue

See dbt's MetricFlow documentation for details on defining metrics.

Then generate the semantic manifest MetricFlow compiles against:

dbt parse

This writes target/semantic_manifest.json, which Dataface reads at compile time. Re-run dbt parse whenever metrics, dimensions, or entities change — Dataface does not invoke dbt itself, it only reads the manifest dbt already produces. A dbt Cloud–hosted project (no local dbt_project.yml/manifest on disk) is not supported by this source; run dbt parse locally or in CI and ship the resulting target/ directory alongside the dbt project.

2. Configure the Source

A metricflow query's source: is an ordinary type: dbt_profile source — the same source type plain dbt-model SQL queries use. There is no separate type: metricflow source config.

# dataface.yml
sources:
  analytics:
    type: dbt_profile
    profile: my_dbt_project
    target: dev

See Sources for profile resolution and connection setup.

3. Reference in Dataface

Reference the metric by name. No SELECT, FROM, or GROUP BY needed.

# dashboard.yml
queries:
  revenue:
    source: analytics
    metrics: [total_revenue]
    dimensions: [order_id__region]
    time_grain: month

Dimension naming

Group-by names follow MetricFlow's own naming convention, not the bare column name:

  • Non-time dimensions are entity-qualified: order_id__region, not region, because the semantic model keys region off the order_id entity.
  • time_grain: month is Dataface's own field — it expands automatically to the reserved group-by name metric_time__month. Don't add a time dimension to dimensions: yourself; use time_grain:.

Chart x:/color:/etc. fields reference these same MetricFlow-native names (metric_time__month, order_id__region), since they are the columns the lowered SQL actually selects.


Flexible Time Grains

Want to see the same metric by week instead of month? Just change one line — each grain recompiles to its own SQL.

queries:
  revenue_weekly:
    source: analytics
    metrics: [total_revenue]
    dimensions: [order_id__region]
    time_grain: week

Multi-Metric Analysis

Combine multiple metrics in a single query to see correlations.

queries:
  overview:
    source: analytics
    metrics: [total_revenue, order_count, average_order_value]
    time_grain: month

Filters and Variables

MetricFlow queries don't support declarative filters: — MetricFlow bakes filter literals into the SQL it generates, so there's no WHERE clause left in the output for Dataface to parameterize with a {{ variable }} at render time. A metricflow query with filters: set fails to compile.

If a board needs the underlying data filtered by a user-facing control, point a plain sql: query's source at the same dbt_profile source and write the metric's SQL directly with a runtime-variable WHERE clause.


Best Practices

To get the most out of this pairing:

  • Name metrics clearly in dbt, such as total_revenue_usd or active_users_7d.
  • Define common dimensions, such as region and customer_segment, in dbt.
  • Test metrics in dbt (mf query --metrics ...) before wiring them into a board.
  • Re-run dbt parse after any semantic-layer change — Dataface compiles against whatever manifest is on disk, stale or not.

Learn More