POWER BI DATA QUALITY
Power BI Data Quality Dashboard, Checks and Monitoring for the Warehouse Behind Your Reports
Power BI shows you a number. It does not tell you the number is wrong. Freshness, volume, schema, and distribution monitoring on the warehouse tables behind every report, read only, with alerts in Slack and PagerDuty, from 99 dollars a month.
14-day trial, no credit card, read-only connection
Alerted #data-eng 0.8s ago.
Downstream impact · consumers at risk
Does Power BI have data quality checks?
Power BI has data profiling but not data quality monitoring, and the difference matters. Power Query column quality, column distribution, and column profile are design time features in the editor: Microsoft documents that they profile the first 1,000 rows by default, and you have to switch them to the entire data set by hand. Power BI data alerts are the closest thing to monitoring, and the documented limits are narrow. Alerts can only be set on gauges, KPIs, and cards pinned from report visuals, they work only with numeric data types, they are explicitly not supported for card tiles with date or time measures, only the person who created an alert can see it, and you get 250 across all your models. Because a date measure cannot carry an alert, the single most common data problem, a table that stopped loading, cannot be alerted on inside Power BI at all. The checks belong upstream, in the warehouse the report reads from, where a stale table is visible before it reaches a single dashboard.
Last updated August 2026
Side by side
Power BI data quality compared
Swipe to see all columns →
| Route to Power BI data quality | What it catches | What you build and operate | Documented limits (Microsoft Learn, August 2026) |
|---|---|---|---|
| Power Query column quality | Valid, Error, Empty, Unknown, and Unexpected error counts per column, shown as a bar under each column name | Nothing. Enable it on the View tab in the Power Query editor | Profiles the first 1,000 rows by default. The switch to Column profiling based on entire data set is a session level toggle in the editor, so it is a design time preview and not a check that runs after the report is published |
| Power Query column distribution and column profile | Distinct and unique value counts, value distribution, and column statistics while you are shaping the query | Nothing beyond enabling it, but somebody has to be sitting in the editor looking at it | Same 1,000 row default. There is no schedule, no history, no threshold, and no notification. Nobody is watching the editor at 3am when the load runs |
| Power BI data alerts | A numeric value on a dashboard tile crossing a threshold you set, checked when the model refreshes | A report visual, pinned to a dashboard as a gauge, KPI, or card, plus an alert rule per tile | Only gauges, KPIs, and cards, only numeric data types, and not supported for card tiles with date or time measures. Only you can see the alerts you set, even if you share your dashboard. Capped at 250 alerts across all your models. No co ownership, so transferring one means recreating it |
| Scheduled refresh failure notifications | A refresh that ran and failed | A refresh schedule and a notification contact list per semantic model | Catches a failure, not a success that delivered bad data. Shared capacity allows eight scheduled refreshes a day, so the alert loop is bounded by the refresh loop. A refresh that succeeds against a table that never loaded is a green tick on top of yesterday numbers |
| A hand built data quality dashboard in Power BI | Whatever your DAX measures assert: row counts, null rates, control charts, last refresh times | The measures, a fact table of check results, the history table, the thresholds, the schedule, and a person who opens it | It is a report, so it is pull not push. It tells you the truth only when somebody looks, and it reads the same semantic model that is already stale when the upstream table is stale |
| Dataobservability | Freshness, volume, schema, and distribution breaks on the warehouse tables your semantic models read, with lineage and grouped incidents | A read only connection to Snowflake, BigQuery, Databricks, or Redshift. No agent, no gateway, no change to the report | Monitors the warehouse, not the Power BI service. It does not read your PBIX files or your workspace, so refresh job health stays a Power BI concern while data correctness moves upstream of it |
Positioning and pricing models are summarized in good faith from each vendor's public pages, August 2026. Verify current terms with the vendor.
What you get
What warehouse level monitoring adds underneath Power BI
Freshness alerting that Power BI structurally cannot do
This is the sharpest gap and it is documented in plain language by Microsoft: alerts are not supported for card tiles with date or time measures, and alerts only work with numeric data types. A last loaded timestamp is a date measure. That means the most common failure in analytics, a table that quietly stopped loading, is the one condition you cannot put a Power BI alert on. Teams work around it by computing hours since last load as a number and alerting on that, which works until the upstream table stops loading and the measure stops updating too, leaving a stale number that never crosses the threshold. Watching the warehouse table directly has no such circularity.
Detection that does not wait for the next refresh
Power BI documents that alerts only work on refreshed data: when data refreshes, Power BI looks to see whether an alert is set, and only then can it trigger. On shared capacity you get eight scheduled refreshes a day, which puts a floor of roughly three hours under how fast any Power BI alert can possibly notice anything, and that is the best case where the refresh itself succeeds on time. The warehouse table changed hours earlier. Monitoring the table means the clock starts when the data breaks rather than when the report next reloads.
Alerts an on call rotation can actually receive
The Power BI documentation is explicit that only you can see the alerts you set, even if you share your dashboard, and that the dashboard owner cannot see alerts you set on their dashboard. Alerts also have no support for co ownership, so when the analyst who built them leaves, the alerts leave with them and the next person has to recreate every one. A monitoring layer that routes per dataset owner into Slack and PagerDuty survives the org chart, because ownership is a property of the dataset rather than of one person login.
Coverage on columns nobody wrote a measure for
Every check inside Power BI exists because somebody built a visual, a measure, or an alert for it. That is a list of things you already thought of. Schema drift is the category that breaks this model: a vendor adds a column, an upstream job retypes an amount from numeric to text, a field gets dropped and a downstream relationship quietly resolves to blank. None of those trip a threshold on a KPI card, and several of them will refresh green. Watching the warehouse catalog for adds, drops, and type changes is a different mechanism from asserting values, and it is the one that catches breakages nobody predicted.
One check for every report that reads the table
A mid sized Power BI estate has the same warehouse tables feeding a dozen semantic models, and a data quality dashboard built inside one workspace tells you nothing about the other eleven. Checks placed at the table are inherited by every report downstream of it, which is both less work to build and less work to keep true. It also means the answer to which reports are affected by this is a lineage query rather than a search through workspaces.
Profiling that persists past the editor session
Column quality and column profile are genuinely useful while you are shaping a query, and they are the right tool for that job. What they are not is a record. The 1,000 row default resets, the toggle to the entire data set is a session level display setting, and none of it is stored, compared against last week, or sent anywhere. Keeping null rates, row counts, and distributions as a time series per table is what turns a one off look at the data into a baseline that can tell you Tuesday was abnormal.
How it works
From connected to caught
Point the monitoring at the warehouse, not the workspace
Connect Snowflake, BigQuery, Databricks, or Redshift with a read only user and let it inventory the schemas your semantic models import from. This is deliberately upstream of Power BI: no gateway, no service principal on the tenant, no change to a single PBIX. Refresh job health stays where it belongs, in the Power BI service, and data correctness moves to the layer where it can be checked before a report ever reads it.
Identify the tables that actually feed reports
Most warehouses have far more tables than any dashboard reads. Start from the tables your semantic models import or query in DirectQuery, usually a short list of marts and views, and make those the first monitored set. Lineage then tells you which upstream tables they depend on, which is the set that can break them. That is a much smaller and much higher value target than monitoring everything on day one.
Let baselines build before you set a single threshold
Give it a few days of load history per table so weekly seasonality becomes visible. A mart that loads hourly on weekdays and never on Sunday is not broken on Sunday, and a hand chosen threshold cannot tell the difference. This is also the period to keep any existing refresh notifications running side by side, because they fail differently: one tells you the pipeline errored, the other tells you the pipeline succeeded and delivered half the rows.
Route to the dataset owner and prune what never fires
Send alerts to the team that owns each schema rather than into one shared analytics channel, so the person who can fix a load is the person who hears about it. After two weeks, read the log back. A monitor that has never fired on a real problem should be relaxed, and any incident that reached you through a stakeholder asking why the numbers look odd should become a monitor. Monitoring that is never pruned turns into noise, and noise gets muted.
Power Query data profiling is a design time preview, not a monitoring system
The three profiling features in the Power Query editor are genuinely good, and they are consistently mistaken for data quality monitoring. Column quality labels values in five categories that Microsoft names precisely: Valid in green, Error in red, Empty in dark grey, Unknown in dashed green, which indicates that when there are errors in a column the quality of the remaining data is unknown, and Unexpected error in dashed red. It shows the count in each category and the percentage. Column distribution gives you frequency and distribution per column, sorted descending, with distinct and unique counts on hover, where distinct means the overall number of different values and unique means values that have only a single instance. Column profile adds a column statistics chart and a value distribution chart you can filter and group by. All three are enabled from the View tab in the Data preview group. Now the part that decides whether this is monitoring: Microsoft documents that by default Power Query performs this data profiling over the first 1,000 rows of your data, and to have it operate over the entire data set you select the Column profiling based on top 1000 rows message in the lower left corner of the editor window to change it to Column profiling based on entire data set. That is a toggle in an editor window. It is not a job, it has no schedule, it keeps no history, it compares against nothing, and it notifies nobody. It answers what does this data look like right now while I am building, which is the question you have at design time. It cannot answer did this table load last night, because nobody is in the editor at 3am. Treating profiling as monitoring is the single most common reason a team believes Power BI is covering data quality when nothing is watching after publish.
What Power BI data alerts can and cannot watch
Data alerts are the only push mechanism Power BI offers on the data itself, and the documented constraints are worth reading carefully before you build a strategy on them. Alerts can only be set on tiles pinned from report visuals, and only on gauges, KPIs, and cards. They only work with numeric data types. They are explicitly not supported for card tiles with date or time measures. They only work on refreshed data and not on static data, and because alerts are only sent when your data changes, an unchanged value does not fire a duplicate. Only you can see the alerts you set, even if you share your dashboard, and the dashboard owner cannot see alerts you set on their dashboard. You can create up to 250 alerts across all your models. There is no support for co ownership, so transferring one to another user means creating a new alert, and recreating the Power Automate flow if you integrated it. Alerts are not available in Power BI Desktop, only the service and the mobile apps. Stack those together and the shape becomes clear. You can alert on a number going above or below a line, privately, on a tile you pinned, up to 250 times, no faster than the model refreshes. You cannot alert on a timestamp, which rules out freshness. You cannot alert on a table having three columns yesterday and four today, which rules out schema drift. You cannot alert on a distribution shifting, only on an aggregate you already put on a card. And the alert belongs to one person rather than to the team that owns the data.
Refresh succeeded is not the same as the data being correct
Most Power BI estates rely on refresh failure notifications as their data quality net, and they catch a real and important class of problem: the gateway went down, credentials expired, the source rejected a query, the refresh exceeded the two hour limit that applies on shared capacity. What they cannot catch is the larger class, where the refresh works perfectly. A refresh reads whatever is in the source table. If an upstream job failed silently at 2am and the table still holds yesterday rows, the refresh succeeds, the notification stays quiet, the dashboard renders, and the number is wrong. There is no error anywhere in the chain, because nothing errored. The cadence compounds this. Microsoft documents that Power BI limits semantic models on shared capacity to eight scheduled daily refreshes, with the quota resetting at 12:01 AM local time, and up to 48 time slots on Premium. Since alerts only evaluate on refresh, eight refreshes a day is a lower bound of roughly three hours on detection even when everything else works. Meanwhile the warehouse knows within minutes: the table has a last modified time, a row count, and a load history, and comparing today against the last few weeks of that history is a cheap metadata query. Checking there means the problem is caught before the refresh runs, which is also the only point where you can stop a bad number from reaching an executive dashboard rather than explaining it afterwards.
Building a data quality dashboard in Power BI, and what it can honestly cover
Plenty of teams build one, and it is a reasonable thing to build. The usual shape is a fact table of check results loaded on a schedule, DAX measures over it, trend lines of valid and invalid records per key table, control charts of daily row counts with statistical bounds drawn on, a completeness heatmap across expected periods, and KPI cards showing how many tables are outdated and when each last refreshed. That is a good design and it makes data quality visible to people who would never open a monitoring tool, which has real value. Be clear eyed about two structural properties though. First, it is pull rather than push: a report tells you the truth when somebody opens it, and the mornings when nobody opens it are exactly the mornings a stale table reaches a board pack. You can bolt an alert onto a KPI card to make it push, at which point every constraint in the section above applies, including the one that stops you alerting on a last refreshed date. Second, and more awkward, the dashboard reads a semantic model that imports from the same warehouse it is meant to be checking. When the upstream table goes stale, the check results table often goes stale with it, and the dashboard shows a green tick computed from yesterday. A monitoring layer that sits outside the reporting stack and reads warehouse metadata directly does not share that failure mode. The two combine well: monitor at the warehouse, then surface the incident history in Power BI for the people who live there.
Tableau data quality warnings, for teams running both
Many US analytics teams run Power BI and Tableau side by side, so it is worth knowing how the equivalent feature behaves. Tableau data quality warnings are part of Tableau Catalog, which ships in the Data Management offering for Tableau Server and Tableau Cloud, so it is a paid add on rather than a base capability. The warning types are Warning, Deprecated, Stale data, and Under maintenance, with custom types available on Tableau Cloud from June 2023. To set one you must be a server or site administrator, or hold the Overwrite capability for the asset. The important detail for anyone comparing this to monitoring is how a warning gets there. Most are set by a human who already knows something is wrong and wants to tell colleagues, and they stay visible until somebody removes them. The automatic path is narrow: Tableau adds a warning when an extract refresh or a flow run fails, and removes it when the operation succeeds. So the Stale data badge, despite the name, is usually a label a person applied by hand, and the automatic trigger is a failed job rather than an assessment of the data. That is the same boundary Power BI draws with refresh notifications. Both products tell you when their own job broke. Neither examines whether the table underneath is right, which is why the check belongs in the warehouse both of them read from.
Questions buyers ask
Power BI data quality FAQ
How do you check data quality in Power BI?
There are three practical routes and they cover different moments. While building a query, enable column quality, column distribution, and column profile on the View tab of the Power Query editor to profile the data, remembering that it samples the first 1,000 rows unless you switch it to the entire data set. After publishing, set data alerts on gauge, KPI, or card tiles for numeric thresholds, and turn on refresh failure notifications for the semantic model. For anything that has to run unattended, including freshness, the check has to live upstream in the warehouse, because Power BI cannot alert on a date measure.
How do you check quality of data in Power Query?
Open the Power Query editor, go to the View tab, and enable the options in the Data preview group: Column quality, Column distribution, and Column profile. In Power Query Online, select Data view and enable them from the drop down. Column quality then labels values as Valid, Error, Empty, Unknown, or Unexpected error with counts and percentages under each column heading. By default this profiles the first 1,000 rows, so select the Column profiling based on top 1000 rows message at the lower left and switch it to the entire data set before you trust the percentages.
Can you set a data quality alert in Power BI?
Only within narrow documented limits. Alerts can be set only on gauges, KPIs, and cards pinned to a dashboard from a report visual, only on numeric data types, and they are not supported for card tiles with date or time measures. They evaluate when the model refreshes, not continuously. Only the person who created an alert can see it, even on a shared dashboard, and you are capped at 250 alerts across all your models. That combination rules out freshness alerting, schema drift, and any team wide on call routing.
Does Power BI detect stale data?
Not on its own. Power BI detects a refresh that failed, which is a different thing. If an upstream table stops loading and still contains yesterday rows, the scheduled refresh reads it successfully, the notification stays quiet, and the report renders stale numbers with no error anywhere. Because alerts are not supported on date or time measures, you cannot put an alert on a last loaded timestamp either. Detecting stale data reliably means comparing each table load time against its own history in the warehouse, before the refresh runs.
What should a Power BI data quality dashboard include?
A useful one usually has four elements: row count trends per key table with statistical bounds so a load that delivered half the usual volume stands out, null and blank rate trends on the columns that matter, a last loaded time per source table with an expected interval next to it, and an incident list showing what broke, when, and whether it is resolved. Feed it from a check results table with history rather than computing checks live, so the dashboard can show change over time. Remember it is a report, so pair it with push alerting that does not depend on somebody opening it.
How do you get a Power BI refresh failure notification?
In the Power BI service, open the semantic model settings, go to the scheduled refresh section, and add the contacts who should be emailed when a refresh fails. Workspace admins can also route failures to Microsoft Teams or a ticketing system through Power Automate or the Power BI REST API. This tells you when a refresh errored. It does not tell you when a refresh succeeded against a table that never loaded, which is the more common and more expensive failure, and it is bounded by the eight scheduled refreshes a day that shared capacity allows.
More of the platform
Catch broken data before your stakeholders do
Connect your warehouse and get power bi data quality live from one read-only connection. Transparent pricing, no credit card.