MetricFlow supports five metric types. Each serves a specific purpose, and choosing the correct type determines whether the calculation aggregates correctly when grouped by a dimension. The types are: simple, cumulative, derived, ratio, and conversion — each documented below, with conditions for when to use it.
Simple Metrics
Simple metrics reference a single measure with one aggregation. They are the building block for everything else.
metrics: - name: order_total label: "Total Order Value" description: "Sum of all order values" type: simple type_params: measure: order_valueThe measure order_value already defines its aggregation (likely sum), so the metric just references it. No additional calculation happens at the metric level.
Use simple metrics for straightforward counts and sums: total revenue, order count, active users. If your metric is “aggregate one column one way,” simple is the right type.
You can also apply filters to narrow the scope without changing the underlying measure:
metrics: - name: enterprise_revenue type: simple type_params: measure: revenue filter: - "{{ Dimension('customer__segment') }} = 'enterprise'"This is preferable to hardcoding filters inside the measure itself, because the same base measure can serve multiple filtered metrics.
Cumulative Metrics
Cumulative metrics aggregate over time windows. Think weekly active users, month-to-date revenue, or rolling 30-day averages.
metrics: - name: weekly_active_users label: "Weekly Active Users" description: "Unique users active in the past 7 days" type: cumulative type_params: measure: active_users window: 7 daysTwo parameters control the behavior:
windowcreates a sliding window (7 days, 30 days). The metric looks backward from each data point.grain_to_dateresets at period boundaries (month-to-date, year-to-date). The accumulation restarts at the beginning of each period.
metrics: - name: mtd_revenue label: "Month-to-Date Revenue" type: cumulative type_params: measure: revenue grain_to_date: monthOne requirement catches people off guard: queries using cumulative metrics with window must include metric_time as a dimension. Without a time dimension, the sliding window has no anchor point. MetricFlow will reject the query rather than silently compute something meaningless.
Derived Metrics
Derived metrics perform calculations using other metrics. They are essential for profit margins, growth rates, and period-over-period comparisons.
metrics: - name: gross_profit label: "Gross Profit" type: derived type_params: expr: revenue - cost_of_goods_sold metrics: - name: revenue - name: cost_of_goods_soldThe expr parameter accepts any valid SQL expression using the referenced metric names. This is where you compose metrics into higher-order calculations.
For period-over-period calculations, use offset_window with an alias:
metrics: - name: revenue_growth_wow label: "Revenue Growth % W/W" type: derived type_params: expr: (revenue - revenue_last_week) / revenue_last_week * 100 metrics: - name: revenue - name: revenue offset_window: 7 days alias: revenue_last_weekThe alias lets you reference the same metric at different time offsets within one expression. Without it, you would have no way to distinguish “revenue now” from “revenue 7 days ago.”
Ratio Metrics
Ratio metrics divide a numerator by a denominator. You might wonder why not use a derived metric for this. The answer is a mathematical trap: the sum of ratios is not the ratio of sums.
If Store A has a 50% conversion rate and Store B has a 25% conversion rate, the combined rate is not 37.5%. It depends on the volume at each store. Ratio metrics handle this correctly by summing numerator and denominator separately before dividing.
metrics: - name: conversion_rate label: "Conversion Rate" type: ratio type_params: numerator: conversions denominator: sessionsYou can apply filters to just the numerator or denominator, which is powerful for segment-specific rates:
metrics: - name: mobile_conversion_rate label: "Mobile Conversion Rate" type: ratio type_params: numerator: name: conversions filter: - "{{ Dimension('session__device_type') }} = 'mobile'" denominator: sessionsThe rule of thumb: if your metric is “X divided by Y” and you want it to aggregate correctly across dimensions, use a ratio metric. If you use a derived metric instead, you risk the sum-of-ratios error that will produce silently incorrect numbers in any grouped query.
Conversion Metrics
Conversion metrics track when a base event leads to a conversion event within a time window. This is funnel analysis: visits to purchases, signups to activations.
metrics: - name: visit_to_purchase_rate label: "Visit to Purchase Rate" type: conversion type_params: entity: user calculation: conversion_rate base_measure: visits conversion_measure: purchases window: 7 daysThe entity parameter defines the join key linking base and conversion events. The calculation parameter can be conversion_rate (percentage) or conversions (count).
For stricter matching, constant_properties ensures attributes match between events:
type_params: entity: user calculation: conversion_rate base_measure: visits conversion_measure: purchases window: 7 days constant_properties: - base_property: "{{ Dimension('visit__device_type') }}" conversion_property: "{{ Dimension('purchase__device_type') }}"This counts a conversion only if the user’s device type matches between the visit and purchase. Without constant_properties, a user who browses on mobile but purchases on desktop would still count as a conversion. Whether that is correct depends on what you are measuring.
Choosing the Right Type
The decision tree is straightforward:
- One measure, one aggregation? Simple metric.
- Aggregation over a rolling or resetting time window? Cumulative metric.
- Math combining other metrics? Derived metric.
- X divided by Y, needs correct aggregation across groups? Ratio metric.
- Event A followed by Event B within a window? Conversion metric.
When in doubt between derived and ratio, ask: “Will this metric be grouped by a dimension?” If yes, and the metric is a division, use ratio. The mathematical correctness is not optional.