Additive vs non-additive metrics
Why some metrics can be summed across dimensions and time, and why others must never be.
The datahashi team3 min read

Not every metric wants a SUM. Account balance, conversion rate, distinct users, and inventory on hand all break if you treat them like order revenue. The mistake shows up as a dashboard that “rolls up” beautifully and means nothing.
datahashi keeps metric meaning in YAML: you declare how a measure behaves, publish an immutable version, and let humans and agents consume the same definition through REST, the console, or MCP. The request shape stays consistent. MCP exposes list_catalog, describe_metric, and run_semantic_query without SQL in or out. Additive versus non-additive behavior belongs in that contract, not in tribal knowledge.
Additive metrics
An additive metric can be summed across a dimension and still be meaningful. Classic examples: gross merchandise value, completed order count, billed minutes. If you have revenue by region and you sum regions, you get company revenue (assuming regions partition cleanly and you are not double-counting).
Additive metrics still need a correct grain. Fan-out joins will inflate them. But once the grain is honest, summing across many dimensions and time periods is usually valid.
Semi-additive metrics
Some measures add across dimensions but not across time, or the reverse. Account balance is the usual teaching example: you can sum balances across customers at a single snapshot date, but summing daily balances across days produces nonsense. Inventory level often behaves the same way.
These metrics need explicit time semantics in the definition: snapshot grain, last-value behavior, or a dedicated period close. If your semantic layer (or your spreadsheet) silently SUMs them across dates, you have a reporting bug wearing a chart.
Non-additive metrics
Distinct counts, ratios, rates, and percentiles are non-additive. Distinct users by country do not sum to distinct users globally when people appear in more than one country. Conversion rate by campaign does not average into conversion rate overall by taking the mean of campaign rates.
For ratios, publish the numerator and denominator as governed components, or publish the ratio with rules that recompute from base measures at the requested grain. Do not pre-sum rates and then hope rollups work.
Put the behavior in the definition
When additive, semi-additive, and non-additive metrics share a catalog without labels, consumers invent the wrong rollup. Analysts sum what should be recomputed. Agents are worse: they pattern-match on “total” and apply SUM everywhere.
A thin layer helps by making the definition the source of truth. datahashi is intentionally thin on top of your warehouse. Metering exists so you can see which metrics are queried. Rollups have shipped. A p99 latency target has not. A rollup that re-aggregates a non-additive measure without a sketch is still a wrong number, and that matters more than advertising speed.
Same rules for humans and agents
If a metric must not be summed across time, that rule has to hold in the console and in MCP the same way. Agents should describe the metric, see its meaning, and run a semantic query rather than inventing SQL that “helpfully” aggregates the wrong way. Humans should not get a special path that rewrites the measure either. Same metric, same request shape, no hallucinated SQL.
A short modeling checklist
- Mark whether the measure is additive, semi-additive, or non-additive in language reviewers understand.
- For semi-additive metrics, state the snapshot or period rule in YAML.
- For ratios, prefer recomputation from base measures at query grain.
- Reject dimension combinations that imply a false rollup.
- Keep warehouse tables thick with history; keep the semantic layer focused on meaning.
Do not sum what must not be summed. Publish the rule once, and let every consumer inherit it.
Product notes
An occasional email when we ship something or write something worth reading.