Orders have an order date and a shipped date. “Orders in May” can mean either, and the Semantic Layer needs to know which one before it can put a metric on a timeline. agg_time_dimension is that choice: the date a metric is counted by, which queries call metric_time.

Copy and paste

One default for the model, one metric that overrides it:

models:
  - name: orders
    semantic_model:
      enabled: true
    agg_time_dimension: order_date          # default for every metric below
    columns:
      - name: order_date
        granularity: day
        dimension:
          type: time
      - name: shipped_date
        granularity: day
        dimension:
          type: time
    metrics:
      - name: order_count
        type: simple
        agg: count
        expr: 1                             # counted by order_date
      - name: shipped_order_count
        type: simple
        agg: count
        expr: 1
        agg_time_dimension: shipped_date    # counted by shipped_date

Query both on one timeline:

mf query --metrics order_count,shipped_order_count --group-by metric_time__month \
  --start-time 2025-04-01 --end-time 2025-07-31
metric_time__month      order_count    shipped_order_count
--------------------  -------------  ---------------------
2025-04-01T00:00:00               1                      1
2025-05-01T00:00:00               2                      1
2025-06-01T00:00:00               1                      2
2025-07-01T00:00:00               1                      1

An order placed on 20 May and shipped on 2 June counts in May as an order and in June as a shipment.

What metric_time is

metric_time is not a column. For each metric, MetricFlow replaces it with that metric’s agg_time_dimension. That is what lets one query put metrics from different models, or with different dates, on the same axis: orders by order date, signups by signup date, shipments by shipped date.

It is also the date that time-based features use: cumulative metrics, offset_window, fill_nulls_with with the time spine, and the --start-time and --end-time options.

The model default and the override

In the legacy format the default sat under defaults: in the semantic model and the override did not exist: a second date meant a second measure. With the latest spec, a metric per date is a few lines.

Grouping by another date

metric_time is the metric’s own date. To group by a different date of the same rows, use the dimension’s name instead:

mf query --metrics order_count --group-by order__shipped_date__month

This groups the orders by shipping month, but the metric is still defined on the order date. Filters on metric_time and the --start-time option still act on the order date. When “shipped orders by shipping month” is a number people ask for regularly, give it its own metric with the override, as above, so that every tool uses the same date.

Tested with dbt Core 1.12 and MetricFlow 0.213 on DuckDB.

References