ServicesAboutNotesContact Get in touch →
EN FR
Note

MetricFlow CLI querying

How to query MetricFlow metrics from the CLI in dbt Core (mf) and dbt Cloud (dbt sl): group-by, filters with Jinja dimension syntax, multi-metric queries, and the semantic manifest.

Planted
dbtanalyticsdata modeling

MetricFlow exposes two CLI interfaces for querying metrics: mf (dbt Core) and dbt sl (dbt Cloud). The commands are equivalent in what they can express; the syntax differs slightly between them. The dbt Cloud semantic layer also adds JDBC, GraphQL, and REST APIs for BI tool connections — those aren’t available in Core.

Generating the semantic manifest

Before any query works, MetricFlow needs a compiled semantic manifest. This is an artifact that tells MetricFlow what semantic models and metrics exist, derived from your YAML definitions.

Terminal window
dbt parse

Run this any time you change semantic model or metric YAML. If you query after a YAML change without re-parsing, MetricFlow will work against the previous manifest and won’t reflect your changes.

The manifest lives in target/semantic_manifest.json. You don’t need to touch this file directly — MetricFlow reads it automatically.

Basic query syntax

The core query structure is --metrics plus optional --group-by:

Terminal window
# dbt Core
mf query --metrics revenue --group-by metric_time
# dbt Cloud
dbt sl query --metrics revenue --group-by metric_time

metric_time is a built-in dimension available on any metric. It uses the agg_time_dimension configured on the underlying semantic model and supports automatic granularity handling.

Querying multiple metrics at once works as long as they share compatible semantic models (MetricFlow can join them through shared entities):

Terminal window
mf query --metrics revenue,orders --group-by metric_time,order__channel

The result is a single query with both metrics as columns, sliced by time and channel.

Dimension references

Dimension names in group-by clauses follow the pattern semantic_model__dimension_name. For the orders semantic model with an order__channel dimension:

Terminal window
mf query --metrics revenue --group-by metric_time,order__channel

This resolves to grouping the revenue metric by the order__channel categorical dimension on the orders semantic model.

You can explore what dimensions are available for a given metric:

Terminal window
mf list dimensions --metrics revenue

This is useful when you’re not sure which dimensions are compatible with a metric — MetricFlow only lists dimensions that can be reached through the semantic graph from that metric’s semantic model.

Filtering with —where

The --where flag applies filters using a Jinja-like syntax that references dimensions through MetricFlow’s resolution engine. You don’t write raw SQL column names — you reference dimensions by their semantic path.

Terminal window
mf query --metrics revenue \
--group-by metric_time \
--where "{{ Dimension('orders__order__channel') }} = 'web'"

The syntax is {{ Dimension('semantic_model__dimension_name') }}. MetricFlow resolves this to the correct column and table, handling any joins required to reach the dimension.

For time dimensions with a specific granularity:

Terminal window
mf query --metrics revenue \
--group-by metric_time \
--where "{{ TimeDimension('orders__order__created_at', 'month') }} >= '2025-01-01'"

The second argument to TimeDimension() sets the truncation granularity. This matters when your filter value is a period boundary — filtering at month grain truncates dates to the first of the month before comparing, which is different from filtering at day grain.

Multiple conditions work with AND:

Terminal window
mf query --metrics revenue,orders \
--group-by metric_time,order__status \
--where "{{ Dimension('orders__order__channel') }} = 'web' AND {{ Dimension('orders__order__status') }} != 'cancelled'"

Controlling time granularity

By default, metric_time returns data at the granularity of the underlying time dimension (typically day). You can request coarser granularity:

Terminal window
mf query --metrics revenue --group-by metric_time__month

The double-underscore granularity suffix works for __day, __week, __month, __quarter, and __year. MetricFlow truncates the time dimension to the requested granularity and aggregates accordingly.

Validation before querying

Before querying, validate that your YAML definitions parse without errors:

Terminal window
# dbt Core
mf validate-configs
# dbt Cloud
dbt sl validate

Common failure modes:

  • “ensure that you’ve ran an artifacts…” — Run dbt parse or dbt build first to generate the semantic manifest.
  • Dimensions not appearing — Every dimension needs a primary entity in its semantic model.
  • Metafont conflict on macOS — The mf command can conflict with the Metafont LaTeX package. Uninstall the LaTeX package if mf gives unexpected output.

The --verbose-issues --show-all flags on validation output more detail when debugging failures:

Terminal window
mf validate-configs --verbose-issues --show-all

What CLI querying is good for

The CLI is suited for development-time exploration: checking that a new metric definition returns expected values, testing filter syntax before encoding it in YAML, and validating that joins work as expected across semantic models.

For production usage, dbt Core’s CLI is the only interface available besides raw SQL against the warehouse. dbt Cloud adds the JDBC and GraphQL APIs that BI tools connect to — every dashboard tool can then consume the same governed metric definitions through the API rather than writing its own SQL.