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
agg_time_dimensionat the model level (next tosemantic_model:) must name a time dimension of the model. Leave it out on a model with metrics anddbt parsestill succeeds, but the first query fails withInvalid aggregation time dimension configuration.agg_time_dimensionon a metric overrides it for that metric only.
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.