Fix the definition before refreshing the dashboard
Two dashboards can query the same warehouse and still disagree about revenue, active customers or conversion. One uses order date, another uses payment date, and a third joins order lines before counting orders. The resulting debate looks like a visualization problem but begins in the definition and grain of the data.
This guide is for analytics engineers and technical decision makers building a metrics layer that teams can trust. The aim is to make business meaning explicit, calculate it consistently and present enough context that users understand what a number includes, excludes and can legitimately be compared with.
Key takeaways
- Define the business question, row grain and eligible population before writing a metric.
- Make joins, time zones, status filters and currency rules explicit.
- Test metric logic with small fixtures and reconciled source totals.
- Separate reusable definitions from dashboard presentation choices.
- Assign owners and version changes that alter historical interpretation.
Write a metric contract in ordinary language
Start with a decision. A product team monitoring onboarding completion needs a different metric from finance reconciling recognized revenue. Document who uses the number, what action it informs and what delay or incompleteness is acceptable. This prevents a convenient existing column from becoming the definition by accident.
A metric contract should include its name, owner, purpose, eligible population, calculation, time field, time zone, dimensions and exclusions. For a conversion rate, specify both numerator and denominator. Explain whether users are counted once per day, once per session or once over the full reporting period.
Give ambiguous words concrete definitions. Active might mean a login, a meaningful product action or a paid subscription. Revenue might mean booked, invoiced, collected or recognized amounts. Those definitions can all be useful, but they should have distinct names rather than competing implementations under one label.
The following YAML is a tool-independent specification sketch. It is not a dbt Semantic Layer API. Implement the agreed meaning in the syntax supported by your selected semantic tool and version.
metric: paid_order_count
owner: commerce_analytics
purpose: monitor completed purchase volume
grain: one order
population:
status: paid
exclude_test_orders: true
calculation: count_distinct_order_id
time:
field: paid_at
timezone: UTC
dimensions:
- sales_channel
- customer_region
freshness:
basis: last_complete_source_interval
changes:
semantic_change: review_and_version
Record unresolved questions before implementation. Whether refunded orders remain in paid order count is a business decision, not something the analyst should infer from whichever status column is easiest to query. A short disagreement resolved explicitly is cheaper than maintaining several incompatible dashboards for months.
Make examples part of the definition
Include a few synthetic records and expected results. A paid test order, a refunded order and an order paid just after midnight can expose hidden assumptions immediately. Examples are especially useful when stakeholders agree with a prose definition but interpret its edge cases differently.
Model grain and joins before aggregation
Grain describes what one row means. A customer table, an order table and an order-line table represent different entities. Joining one order to several lines repeats the order's attributes. Summing an order total after that join multiplies revenue even if the SQL is syntactically correct and every key is valid.
Choose a base model at the metric's intended grain. Aggregate child tables before joining when their details are needed only as a summary. For dimensions that change over time, decide whether historical facts should use the dimension value at the event time or the latest value. Both answer different questions.
+----------------+ +------------------+
| Source records | --> | Tested base models|
+----------------+ +---------+--------+
|
+---------v--------+
| Grain + join rules|
+---------+--------+
|
+---------v--------+
| Shared metrics |
| Time + dimensions|
+---------+--------+
|
+-----------------+----------------+
| |
+---------v---------+ +---------v---------+
| Operational views | | Decision dashboards|
+-------------------+ +-------------------+
This runnable PostgreSQL example aggregates line amounts before joining to orders. It uses synthetic values and demonstrates join safety, not an accounting definition. A real revenue metric needs its own treatment of discounts, tax, refunds and currency conversion.
WITH orders(order_id, channel) AS (
VALUES ('o1', 'web'), ('o2', 'store')
), lines(order_id, amount_minor) AS (
VALUES ('o1', 1200), ('o1', 800), ('o2', 500)
), order_amounts AS (
SELECT order_id, sum(amount_minor) AS amount_minor
FROM lines
GROUP BY order_id
)
SELECT o.channel,
count(*) AS order_count,
sum(a.amount_minor) AS amount_minor
FROM orders o
JOIN order_amounts a USING (order_id)
GROUP BY o.channel;
Test uniqueness at the declared grain and relationships between models. A uniqueness test on a surrogate row identifier does not prove there is only one row per business order. Add explicit checks on the business key and investigate any join that changes the expected number of rows.
Define time, ratios and non-additive measures
Time is part of the metric. Order-created date, payment date and shipment date describe different events. State which one controls the reporting period and how time zones are applied. A daily chart grouped in UTC cannot be compared directly with one grouped in a regional business time zone without explaining the boundary difference.
Ratios should usually be calculated from their underlying numerator and denominator at the requested aggregation level. Averaging daily conversion rates can produce a different result from total conversions divided by total eligible sessions. Choose the intended meaning and keep both components available for validation.
Distinct counts are not generally additive across overlapping groups. A user active on two days should count twice in summed daily active users but once in monthly distinct active users. Balances also behave differently from flows: summing end-of-day account balances across a month does not produce a meaningful monthly balance by default.
| Measure type | Example | Aggregation concern |
|---|---|---|
| Additive flow | Units sold | Consistent units and eligible records |
| Ratio | Conversion rate | Recompute from numerator and denominator |
| Distinct count | Active customers | Overlap across time and dimensions |
| Point-in-time balance | Inventory on hand | Choose snapshot time and carry-forward rules |
Currency conversion requires an explicit rate source and effective time. Do not combine amounts in different currencies and attach one currency label afterward. Preserve original amounts and conversion metadata so a revised rate policy can be reviewed and reproduced.
Treat incomplete periods honestly
A chart comparing today's partial sales with yesterday's full day invites a misleading conclusion. Show completion status, use comparable elapsed windows or clearly label the comparison as partial. Freshness should describe the last complete source interval, not only the dashboard's refresh timestamp.
Define how late-arriving records change historical periods. Some metrics are restated as better data arrives; others need a frozen reporting view with separate adjustments. Communicate the policy and make it visible to users who export numbers for presentations or recurring reports.
Choose a metrics layer that matches your consumers
A metrics layer centralizes definitions and supported dimensions so different tools can request consistent calculations. It can live in carefully managed SQL models, a semantic service or a combination. The right choice depends on the number of consumers, query patterns, access rules and the team's ability to operate another layer.
The MetricFlow documentation describes dbt's approach to constructing metrics queries from semantic definitions. Before adopting any implementation, check supported metric types, join behavior, deployment model and integration requirements for your version. A semantic tool cannot resolve an undefined business concept on its own.
Separate reusable meaning from presentation. A metric definition should not change because one dashboard uses a bar chart and another uses a table. Conversely, dashboard-specific filters must be visible so users understand why a displayed slice differs from the global metric.
Access rules belong in the serving path as well as the data models. A user allowed to see an aggregate may not be allowed to drill into individual records. Test the interaction between row restrictions, dimension filters and cached results. Shared definitions are valuable only if they also preserve appropriate data access.
Introduce the layer incrementally
Start with a small set of disputed, widely used metrics. Document their definitions, reconcile them with stakeholders and replace duplicate dashboard logic. Keep old and new outputs available during a controlled comparison period so differences can be explained rather than hidden behind a launch date.
Measure adoption by whether teams use the definitions to answer real questions, not by how many YAML files exist. If users repeatedly bypass the layer, investigate missing dimensions, slow queries or unclear semantics. Governance works better when the standard path is useful and understandable.
Test definitions and design useful dashboards
Use small fixtures that expose edge cases: duplicate joins, null dimensions, zero denominators, refunded transactions and daylight-saving boundaries where relevant. Expected results should be reviewed by the metric owner. This turns business interpretation into regression protection rather than relying only on analyst memory.
Reconcile important totals against an authoritative operational or financial source using an agreed comparison window. Explain legitimate differences in timing and scope. A reconciliation that demands exact agreement between differently defined measures can create endless false alarms, while no reconciliation leaves silent errors undiscovered.
The data contracts and quality guide provides the upstream counterpart. Metrics depend on source meaning and completeness, so quality status should flow into the dashboard rather than disappear after transformation.
A useful dashboard shows the metric definition, reporting period, relevant filters and freshness. Put the decision-oriented view first, then provide a path to detail. Avoid packing unrelated metrics into one page merely because they are available. Each visualization should help answer a question or identify a condition that warrants action.
Rehearse a definition change
Suppose the active-customer definition changes from login activity to a meaningful product event. Produce both series over the same historical window and explain the difference. Version the definition, annotate the effective date and decide whether historical charts are restated. Do not splice the two series together as if nothing changed.
Notify owners of downstream exports, scheduled reports and alerts. A threshold calibrated for the old definition may become meaningless under the new one. Updating the central metric is only the first step; the decisions built on top of it need review as well.
Common mistakes
- Using familiar labels such as revenue or active without explicit definitions.
- Summing repeated parent values after joining to a lower-grain table.
- Averaging ratios or adding distinct counts across overlapping groups.
- Showing a fresh dashboard timestamp when source data is incomplete.
- Changing metric meaning without versioning or notifying downstream owners.
Checklist
- Define the decision, owner, population and calculation for each metric.
- Document grain, join paths, time zones, units and exclusions.
- Keep numerator and denominator available for ratio validation.
- Test edge cases with small synthetic fixtures.
- Reconcile important totals against an agreed authoritative source.
- Display filters, freshness and incomplete-period status.
- Version semantic changes and review downstream alerts and reports.
FAQ
What is a metrics layer?
It is a shared place to define calculations, dimensions and their meaning so consumers request consistent results. Its implementation can range from governed SQL models to a dedicated semantic query service.
Will a semantic layer fix conflicting business definitions?
No. Stakeholders still need to agree on what each metric means. The layer helps encode and distribute that agreement once it exists.
Why do two dashboards disagree on the same data?
Common causes include different time fields, filters, grains, joins or treatment of incomplete periods. Compare those assumptions before assuming that one visualization tool has a calculation bug.
Should every dashboard show the same metrics?
No. Different decisions require different measures and levels of detail. Reuse definitions where the meaning is shared, while making task-specific filters and interpretations explicit.
Final thoughts
Trusted dashboards begin with trusted definitions. Establish grain and meaning, test the calculations and give users enough context to interpret a number before asking them to act on it.
For help building that foundation, explore my analytics and visualization service and book a conversation.

Comments
No comments yet. Start the conversation.
Leave a comment