Classify the disagreement before investigating it
There are five kinds of divergence and they have different owners. A data defect means one number is wrong. A definition difference means both are right about different questions. A modelling defect means the query computed something other than what the author intended. A freshness difference means the same number at two points in time. A business disagreement means two teams genuinely measure different things on purpose.
Skipping this classification is why reconciliations take days. An engineer assumes a data defect and starts inspecting pipelines; the actual cause is that one dashboard excludes intercompany transactions because finance requires it and the other does not because commercial does not care. No amount of pipeline inspection surfaces that, because nothing is broken.
The fastest opening question is therefore not "which is wrong" but "should these be equal at all". Surprisingly often the answer is no, and the correct outcome is a label on each dashboard instead of a fix to either.
Grain: what one row represents
Grain is the most common cause and the one people check last. If one model has a row per order and the other a row per order line, any join to a header-level attribute will multiply or collapse values, and totals will differ in a way that looks like a data problem. Nothing is broken; the two models are counting different things.
The symptom worth recognising is a discrepancy that is small on some slices and large on others. Orders with one line reconcile perfectly; orders with six do not. That pattern is almost diagnostic on its own, and it points at a fan-out in a join rather than at missing or duplicated source data.
In a semantic model this shows up through relationship cardinality. A one-to-many relationship traversed in the wrong direction, or an ambiguous path between two tables where more than one relationship could apply, produces exactly this. Power BI's documentation is explicit that only one relationship between two tables is active at a time and that changing the active path changes results — which is what makes a second, inactive relationship such a reliable source of quiet divergence.
The check is mechanical: for each model, count rows and count distinct business keys. If the two differ, you have your grain, and everything built on top inherits it. This is the same discipline warehouse modelling applies before naming any layer, and the reason it comes first there too.
Filters, exclusions and the rule nobody documented
Most dashboards quietly exclude something: cancelled orders, test accounts, internal transactions, refunds, a legacy region, staff purchases. Each exclusion was a reasonable decision made once, usually in a conversation, and almost never written anywhere the next analyst will find it. Two dashboards with different exclusion lists will never agree and neither is wrong.
Row-level security produces the same effect with an extra twist: the number depends on who is looking. Two people opening the same dashboard see different totals, and neither sees anything indicating a filter was applied. When a reconciliation involves two people comparing screens, confirm they hold the same role before comparing anything else.
The other quiet filter is the visual's own context. In a semantic model a measure is evaluated against whatever filters the report applies — slicers, page filters, the row and column headers of the visual itself. Microsoft's own framing is that a measure's result cannot be determined without context and is evaluated separately for each cell. Two visuals of the same measure can therefore differ purely because of where they sit, with no difference in the underlying model at all.
- List every exclusion in each model and diff the lists before touching data
- Confirm both viewers hold the same security role
- Check slicers, cross-filters and page-level filters, not only the query
- Record each exclusion as part of the measure definition, not as tribal knowledge
Time is three different questions
"Revenue in March" has at least three answers depending on which timestamp defines the period: when the order was placed, when it was fulfilled, or when it was recognised in the ledger. Add the distinction between event time and processing time, a fiscal calendar that does not match the Gregorian one, and time zones, and two dashboards can disagree while both using March correctly.
Time zone handling is the sharpest edge because it moves individual transactions across boundaries instead of changing every value. A late-evening order in one region lands on a different day depending on whether the model stores local time, UTC, or a converted value — and month-end is where the effect concentrates, which is exactly when the reconciliation meeting happens.
Late-arriving data produces a subtler version: a transaction for March that arrives in April. Whether March's published figure changes depends on the late-arrival policy, and if two models made different choices, they will agree in real time and diverge after restatement. This is the same decision every ingestion pattern has to state explicitly, and leaving it implicit is how two reports drift apart weeks after both were correct.
Snapshot timing belongs here too. A measure computed as "customers active as of the snapshot" depends on when the snapshot ran; compare a nightly snapshot to a live query and they will differ by exactly one day of activity, every day, forever.
Identity: what counts as one customer
Customer counts diverge more often than revenue, and the cause is usually identity rather than arithmetic. If one model counts distinct account IDs and another counts distinct resolved customers after deduplication, the second is always lower, and the gap is the merge rate. Both are defensible; they answer different questions.
Slowly changing dimensions turn this into a moving target. If a customer's segment changed in June, a report attributing history to their current segment and a report attributing it to the segment at transaction time will disagree about every month before June — and both are legitimate, because "revenue from enterprise customers" is genuinely ambiguous about whether it means customers who are enterprise now or were then.
Where identity resolution exists at all, the resolved key belongs in the model that reports on customers, and the reporting layer should say which one it uses. A Customer 360 build exists precisely to make that key authoritative, and its value is largely that this argument stops recurring.
Refresh state, and the number that was right an hour ago
Two dashboards reading the same tables at different times show different numbers, and nothing about either display indicates that. Add caching, import-mode models refreshed on separate schedules, and incremental refresh windows, and two reports can be hours apart while both look current.
The fix is display instead of engineering. Show the underlying data's as-of timestamp on the report, not the time the page was opened — those are different, and the second is the one people assume. A visible as-of time resolves a large share of reconciliations in seconds, before anyone opens a query.
Partial refresh failure is the dangerous variant. When one model in a chain fails and the rest succeed, the report renders completely with one stale component, and the only signal is a number that looks slightly off. This is the case for holding the publish instead of serving a partial result, and for treating a failed refresh as an incident with a named responder instead of a log entry.
A sequence that finds it in under an hour
Work from cheapest check to most expensive, and stop at the first difference — the sequence below is ordered by how often each step is the answer divided by how long it takes to check. Most reconciliations end at step three, and almost none require reading transformation code, which is where people tend to start.
Two disciplines make this work. Write down the result of each step for both dashboards before moving on, because the cause is frequently visible in the accumulated comparison rather than in any single step. And agree the reconciliation target first: a specific measure, a specific period, a specific slice. "The numbers don't match" is not something anyone can investigate.
- 1. Confirm both are the same measure name meaning the same thing — read both definitions aloud
- 2. Confirm the same time basis, period boundaries and time zone
- 3. Diff the filters, exclusions and security roles in force for each viewer
- 4. Compare grain: row counts and distinct business keys per model
- 5. Compare the source tables each model actually reads
- 6. Check as-of timestamps and last successful refresh for both
- 7. Only now read the transformation logic, narrowed to the difference found above
- 8. Reconcile the residual explicitly and record it, instead of declaring a match
Symptom, likely cause, verification, owner
The shape of a discrepancy usually points at its cause before any investigation. A constant offset, a proportional gap, a difference confined to one slice and a difference that changes hour to hour each come from a different family of problem, and reading the shape first saves most of the work.
The owner column is the part that makes this actionable. Roughly half of these are not engineering problems at all, and routing them to an engineer guarantees a slow resolution and an unresolved disagreement underneath.
| Dimension | Likely cause | How to verify | Who owns the fix |
|---|---|---|---|
| Constant absolute offset | A fixed set of records excluded from one model. | Diff the exclusion lists; count the excluded rows and compare to the gap. | Metric owner. |
| Gap proportional to volume | Grain mismatch producing fan-out on a join. | Row count and distinct business key per model. | Analytics engineer. |
| Only multi-line orders differ | Header attribute joined at line grain. | Filter to single-line orders and re-compare. | Analytics engineer. |
| Month-end only | Time zone or period-boundary difference. | Compare a single day's transactions either side of midnight. | Analytics engineer. |
| Historic months changed | Late-arriving data restating a closed period. | Compare against a prior export of the same period. | Data owner sets the policy. |
| Customer count differs, revenue matches | Identity resolution applied in one model only. | Count distinct account IDs and distinct resolved customers. | Data owner. |
| Differs by viewer | Row-level security or a personal filter. | Two people open the same report and compare roles. | BI platform owner. |
| Differs by hour | Refresh schedule, caching or a partial refresh failure. | Compare as-of timestamps and refresh history. | Pipeline owner. |
| Same visual, different pages | Report filter context, not a model difference. | Inspect slicers and page filters applied to each visual. | Report author. |
| Drifted apart gradually | One definition changed and the other did not. | Compare current definitions against the last agreed version. | Metric owner. |
| Neither matches the source system | A genuine pipeline or reconciliation defect. | Reconcile counts and totals back to source. | Pipeline owner. |
Fixing the cause instead of the symptom
Reconciling two dashboards once solves one meeting. The same pair will diverge again within a quarter unless the definition lives in one place that both consume. That is the actual remedy, and it is a governance change instead of a reporting one: one definition, one owner, one model that other reports build on rather than reimplement.
A governed semantic model with certified measures is the mechanism, and its value is precisely that it removes the opportunity for divergence instead of detecting it afterwards. A measure defined once and inherited cannot drift; a measure reimplemented in four reports will.
Alongside that, the exclusions and the time basis have to be written into the definition instead of living in the query. "Net revenue" is not a definition. "Net revenue: invoiced amount less credit notes, excluding intercompany, on ledger recognition date, in reporting currency at month-end rate" is one — long, unglamorous, and the reason the argument stops.
There is also a monitoring answer. A reconciliation check comparing the certified measure against a source control total, run on a schedule, catches drift before a meeting does. That is a stated quality rule instead of a behavioural signal, and it is one of the few checks that pays for itself in a single avoided investigation.
When the answer is that both should stay
Not every divergence should be resolved into one number. Finance and commercial teams frequently need genuinely different measures — one on recognition date excluding intercompany, one on order date including everything — and forcing them into a single definition produces a number neither team trusts and both work around.
When that is the case, the deliverable is labelling rather than convergence: two measures with different names, each with its stated definition and owner, and a documented explanation of why they differ and by roughly how much. The failure to avoid is two measures with the same name.
This article also assumes both dashboards read the same warehouse. Where one reads the warehouse and another queries an operational system directly, you are comparing two systems with different consistency guarantees and different update timing, and reconciliation there is a different and considerably harder exercise.
Questions and trade-offs
Question
Which number should we present while this is unresolved?
Present one, name its definition on the slide, and say the other exists and why it differs. Presenting both without explanation transfers the confusion to the audience; presenting one silently means the disagreement resurfaces later with less goodwill. The choice of which to present follows the decision being made — a recognition-date figure for a board pack, an order-date figure for a commercial review.
Question
Should every measure live in one semantic model?
Every measure that more than one team reports on, yes — that is where divergence comes from. An analyst exploring a question for themselves does not need to certify anything, and requiring it slows exploration for no benefit. The line is publication: the moment a number leaves the analyst's screen and enters a recurring report, it needs a definition, an owner and one implementation.


