Every Power BI report works perfectly when you first build it. Then six months pass. Someone adds a new page, someone else duplicates a measure "just for testing," a data source changes and nobody updates the documentation. Slowly, the report accumulates debris.
The problem is that none of this causes an error. Power BI won't tell you about unused measures, unnecessary columns, or relationships that no longer serve a purpose. The report loads, the visuals render, and everyone assumes things are fine.
Until the report takes 45 seconds to refresh, or a calculation silently returns wrong numbers because it references a measure that was supposed to be updated but wasn't.
A regular health check catches these problems before they compound.
What to look for in a health check
Unused measures
This is the most common issue in mature reports. Measures get created during development, used on a visual, then the visual gets removed or redesigned. The measure stays.
In a report with 200 measures, it's not unusual to find 40-50 that are completely unused — not referenced by any visual and not used in any other measure's DAX expression. They're dead weight that makes the model harder to navigate and maintain.
Finding them manually means checking each measure against every visual and every other measure. That's slow and error-prone. A tool that can parse the visual definitions and DAX dependencies does it in seconds.
Orphan columns
Similar to unused measures, but for columns. An Import-mode table with 30 columns where only 8 are used in visuals or DAX means 22 columns are consuming memory for no reason. This is one of the most impactful performance improvements you can make — removing unused columns from Import tables directly reduces the dataset size.
The trick is that a column might look unused but actually be referenced in a relationship, a filter, or RLS rule. A proper audit checks all of these.
Broken or questionable relationships
These are harder to catch visually. Look for:
- Inactive relationships — Power BI allows multiple relationships between tables but only one can be active. Sometimes developers create inactive ones intending to use USERELATIONSHIP in DAX, but then never do. The inactive relationship just adds confusion.
- Many-to-many relationships — Sometimes intentional, often accidental. If you didn't explicitly design a many-to-many, it's worth investigating why one exists.
- Bi-directional cross-filtering — This can cause unexpected results and performance issues. Unless you specifically need it (and understand the implications), single-direction is safer.
Model size vs actual use
A quick sanity check: how large is the model compared to what the visuals actually need? If you have 15 tables but only 6 appear in any visual or DAX expression, the other 9 might be leftovers from development or imported "just in case."
Every unnecessary table in an Import-mode model increases refresh time and memory consumption in the Power BI service. For Pro users with 1GB dataset limits, this matters.
DAX complexity flags
Some patterns in DAX are worth flagging:
- Deeply nested CALCULATE statements — Often a sign that the filter context is being manipulated in hard-to-follow ways
- Measures that reference more than 5 other measures — These deep dependency chains are fragile and hard to debug
- EARLIER or LOOKUPVALUE in calculated columns — These are older patterns that can often be replaced with more efficient alternatives
These aren't necessarily bugs, but they're maintenance risks worth knowing about.
How often should you run health checks?
For actively developed reports, before each major release. For reports in production, quarterly is a reasonable cadence. The goal isn't to achieve a perfect score — it's to catch problems while they're small.
If you use version control with PBIP format, you can diff the health check results between versions. "Last check showed 12 unused measures, now there are 18" tells you the model is accumulating debt.
Manual vs automated health checks
You can do a health check by hand. Open DAX Studio, query the model metadata, cross-reference with Power BI Desktop. It takes a few hours for a complex model, and you need to know what to look for.
Automated tools like Dummy BI Automate read the PBIP project files and flag issues programmatically. Unused measures, orphan columns, relationship anomalies, and DAX complexity indicators are all things that can be detected by parsing the TMDL and PBIR files without needing a running instance of the model.
The advantage of automation is consistency. A tool checks the same things every time. A person doing it manually will focus on what they remember to check and miss the rest.
The bottom line
Health checks are unsexy work. Nobody's going to show a health check report in a team meeting and get applause. But the alternative — waiting until users report slow performance or wrong numbers — is far more expensive to fix.
Build health checks into your workflow. Run them regularly. Fix what you find. Your future self (and whoever inherits your reports) will thank you.