Articles · Business intelligence · · 7 min read
Dashboard Decay and the Review Habit
Reports rot quietly: definitions drift, audiences move on, copies multiply. A concrete review habit that keeps a reporting estate honest without a rebuild.
By Matthieu de La Mettrie · Founder, Skopura
Nobody schedules dashboard decay. It arrives by accretion: a filter pinned for one meeting that nobody unpins, a measure forked into a page-local variant, a page kept alive because one executive once asked for it. The estate does not fail — it thickens. And a thickened estate is worse than a broken one, because a broken report gets fixed and a thick one gets worked around.
The fix is not a rebuild. It is a habit with a date in the calendar and a person’s name on it.
What does a decaying dashboard actually look like?
Not an error message. Decay presents as behaviour, and the behaviour is easy to miss if you only watch refresh status.
The first symptom is the shadow extract. Somebody exports to a spreadsheet before every meeting, because the report answers a question adjacent to the one they now have. The report still refreshes. It is still green. It is also no longer the artefact anyone makes a decision from.
The second is the fork. A measure gets copied into a new report and modified — a different denominator, a different date grain, an extra filter for a business unit that reorganised. Both versions are defensible in isolation. Neither is reconcilable at a meeting, so the meeting stops using either and asks an analyst instead.
The third is the orphan page. A page exists, refreshes, and is opened by nobody. It carries cost anyway: it pins columns in the model that would otherwise be droppable, it appears in impact analysis whenever someone touches an upstream table, and it makes the estate look larger and more fragile than it is.
The fourth is filter archaeology. The default slicer state encodes a decision made when the report was built. Nobody remembers the reason. Changing it feels risky, so it stays, and every number on the canvas quietly inherits an assumption that has expired.
Why does decay start at the model, not the canvas?
Because the canvas is downstream of a contract, and the contract is the semantic model. A semantic layer centralises metric definitions so separate reports agree. When that centralisation is partial — some measures in the model, some in the report, some in a calculated column that once solved a deadline — the guarantee that separate reports agree has already lapsed. The visuals are just where you notice.
So the review must be able to reach the model. A review that can only comment on layout produces prettier decay.
Which signals are worth collecting?
Only the ones you will act on. An audit that produces a spreadsheet nobody reads is itself a decaying report.
Start with an inventory: every report, its semantic model, its owner, and the decision it exists to support. The last field is the one people resist writing, and the one that does the work. “Monthly revenue visibility” is not a decision. “Which accounts go to the retention queue this month” is.
Then attach activity. Platform activity logs give you who opened what and when. Join that to the inventory and the orphan pages surface without argument. Attach refresh history too — a model that fails intermittently and is repaired by hand is a model whose consumers have already learned to distrust it.
Finally, attach definition lineage: which measures are defined in the model, which are defined in the report, and which exist in both with different logic. That last set is your reconciliation backlog.
-- illustrative shape, not a specific platform's schema
with opened as (
select
report_id,
count(distinct user_id) as distinct_viewers,
max(event_ts) as last_opened
from activity_events
where event_type = 'ViewReport'
and event_ts >= :window_start
group by report_id
)
select
i.report_name,
i.semantic_model,
i.owner,
i.decision_supported,
o.distinct_viewers,
o.last_opened,
d.report_local_measures
from report_inventory i
left join opened o
on o.report_id = i.report_id
left join definition_audit d
on d.report_id = i.report_id
order by o.last_opened nulls first;What does the review itself contain?
A fixed agenda, a short list, and a decision per item. The failure mode of a review is discussion without disposition.
For each report on the list, ask: who opened it in the window; what decision it changed; whether its measures still match the model. Anything that cannot answer all three is a candidate for retirement or absorption. Retirement means the surface goes and the definition is archived somewhere recoverable — you want to be able to answer “what did that report actually compute” a year later without a forensic exercise.
Absorption is the more common outcome and the more useful one. Two reports with the same grain and different filters usually want to be one report with a field parameter or a bookmark set. That collapses maintenance surface without taking anything away from anyone, which is what makes it politically survivable.
Retire the surface, archive the definition
Report-level fix or model-level fix?
The canvas is always faster and almost always wrong. The question is which failure you are buying.
| Fix at the report | Fix at the model | |
|---|---|---|
| Blast radius | One report, one audience | Every report on the model |
| Time to ship | Same sitting | Needs review and republish |
| Durability | Survives until the next fork | Survives until the definition genuinely changes |
| Who can do it | Any report author | Whoever owns the model contract |
| What decays next | Definition drift between reports | Nothing, if the change is documented |
A useful rule: report-level changes are permitted for layout, interaction and narrative. Anything that changes a number belongs in the model. Enforcing that one boundary removes most reconciliation work before it starts.
Does retiring reports save anything?
Not directly. Removing a page from a workspace does not reduce refresh work — the model still loads the columns and partitions it loaded before. Savings come from narrowing the model: dropping columns nothing references, coarsening a grain nothing queries at, or restructuring how partitions are processed. Incremental refresh processes only changed partitions rather than a full dataset, which changes the shape of the refresh bill; retirement changes the shape of the maintenance bill.
That distinction matters when you pitch the habit internally. Sell it as cost reduction and someone will check the invoice and find nothing moved. Sell it as reducing the number of things that can silently disagree, and the case holds on its own terms.
Who owns the habit?
One named person per semantic model, not per report. Report ownership fragments; model ownership is where the contract lives, and the contract is what you are defending.
That owner runs the review on a cadence the estate can sustain — frequent enough that the list stays short, infrequent enough that people prepare for it. They bring the inventory join, the reconciliation backlog, and a proposed disposition for every item. The meeting confirms or overrides; it does not discover.
The habit compounds in an unglamorous way. The first review is long and uncomfortable, because it surfaces every fork and orphan at once. The second is shorter. By the third, the interesting conversation is no longer “which of these numbers is right” but “is this still the decision we are making” — which is the conversation reporting was supposed to enable in the first place.
power-bi · semantic-layer · reporting · data-quality
Share on LinkedIn ↗Work with Skopura
Facing this bottleneck in your own estate?
Skopura builds production-grade lakehouse pipelines, evaluation harnesses, and provides fractional data leadership. Thirty-minute call, no deck.