The Dashboard Is Slow and Nobody Owns It: Running BI at Company Scale
A company buys a BI tool, and for a year everything works. Then someone counts: four hundred dashboards, nine tables that all claim to hold revenue, a Monday morning when every report is slow, and one analyst who left in March and owned eleven of the things executives read. Nobody did anything wrong. The tool made the first dashboard easy and did nothing to make the four hundredth manageable.
Both Power BI and Tableau are good at the first problem and neutral about the second. What follows is the second: the decisions that determine whether a BI platform stays usable as the number of authors, reports, and readers grows. Product details below follow the Microsoft Learn and Tableau documentation as of September 2026 — this is an area where specific limits change, so check the current pages before you plan against a number.
Where the data sits decides everything downstream
Every BI tool offers the same fundamental choice: copy the data into the tool’s own engine, or query the source each time. Power BI calls these Import and DirectQuery; Tableau calls them extracts and live connections. The names differ and the trade does not.
| Copy it in (Import / extract) | Query the source (DirectQuery / live) | |
|---|---|---|
| Query speed | Fast — an engine built for it. Tableau documents that extract-based views show “better performance compared to views connected directly to the original data” | As fast as the source under concurrent load, which is usually the real constraint |
| Freshness | As of the last refresh. There is always a gap, and someone has to decide how large it may be | Current as of the last query the report actually ran — which is not the same as continuously current |
| Load on the source | Concentrated in the refresh window | Spread across the interactions that miss the caches — including the ones nobody planned for |
| What it costs you | Memory and refresh capacity in the BI platform | A source that must absorb interactive query patterns it was not sized for |
| Offline use | Possible — extracts “allow for offline access to data” | No |
“Current at query time” is the claim that needs qualifying, because a reader looking at an open report is usually not at query time. Microsoft’s documentation is direct about it: with DirectQuery, “changes in source data appear only after actions that requery (navigation, slicer/filter changes, manual refresh),” and “caches (visual, tile, result) mean a visual can show prior results until refreshed.” Dashboard tiles are further removed still — they “refresh on a schedule to cache tile results for fast dashboard opening” and “show the results from their last scheduled refresh unless manually refreshed,” with the default hourly and the floor every fifteen minutes. There is also no guarantee that one page is internally consistent: “visuals aren’t always time consistent,” since different queries can run moments apart.
Which matters operationally in one specific way. A reader who leaves a live dashboard open on a wall is not watching current data, and neither is one reading a pinned tile. If a decision depends on freshness, the report has to either refresh itself on an interval or state the time the numbers were fetched — and if the answer must be current to the second, a BI tool is the wrong instrument regardless of connection mode.
Two further consequences are worth stating before the first model is built. On a live connection, a filter click that has to be answered from the source puts load on an operational or warehouse system — not every click does, since the service “caches some results” and an “exact repeat” query can be served from cache, and an aggregation table can absorb a common query without touching the source. What this means for planning is that capacity comes from the queries that actually reach the source, so the number to measure is the cache miss rate and the source-side query volume rather than the number of interactions. And a copy is a copy: it is a second place the numbers live, with its own refresh state, and the reporting cutoff it implies has to be stated on the report rather than assumed by the reader.
Where the copy exists, incremental refresh is what keeps the cost bounded. Both products offer it, both scope it to a window you choose, and the window is where late corrections are won or lost.
Tableau’s basic form appends: configured to “add only the rows that are new since the previous time you extracted the data,” it does not revisit rows already in the extract. Since version 2024.2 it can also do more than append — specifying a minimum date range to refresh pulls “any new data, plus previously extracted data from a set time range,” which re-extracts that past window and so picks up changes made inside it. Two documented constraints are worth knowing before relying on it: a source whose timestamps are more precise than Tableau’s can leave “duplicate rows after an incremental refresh,” and a structural change such as an added column means “you’ll need to do a full extract refresh before you can start doing incremental refreshes again.”
Power BI partitions the table by date instead. A policy defines a refresh period and a historical period; with each refresh, rows “with a date/time within the refresh period are refreshed,” and rows that fall out of it “become part of the historical period, which isn’t refreshed,” with both windows rolling forward. So corrections are picked up automatically as long as they land inside the refresh window and carry a date in it — a three-day window catches a correction made today to yesterday’s row, and misses one made today to a row dated last month. There is also a Detect data changes option that uses a separate audit timestamp to skip periods whose data has not changed, narrowing the work further rather than widening the window.
So the products differ in mechanism and agree in what they demand of you. Each re-reads a window you nominate and neither notices a correction outside it: Power BI misses one landing before its refresh period, Tableau one landing before its subrange — and Tableau’s plain append configuration misses every correction, since it re-reads nothing.
The decision this forces is usually left unmade: how far back a correction is allowed to arrive. That answer sets the window, or the full-refresh schedule, and without it late corrections are absorbed silently — the report is simply wrong in a way no refresh log shows.
Refresh is the expensive operation, not the queries
Teams size a BI platform for reading and are surprised by refresh. The Power BI documentation explains why with a detail worth memorizing: a refresh “causes the memory used by the semantic model to more than double, because in addition to the memory used by the refresh operation, the original copy of data remains available for active queries while another copy is being processed by the refresh.”
Read that as a capacity rule. A 20 GB model needs well over 40 GB available to refresh while people are reading it, and query memory stacks on top: “The memory used to query the semantic model is added to the memory needed to load the semantic model, and refresh it.” Against documented per-SKU ceilings — 25 GB maximum model memory on an F64, 100 GB on an F256 — a model that fits comfortably at rest can fail to refresh at nine on a Monday. The failure looks like a mysterious refresh error, not like a memory limit.
Scheduling has a similar trap. Power BI states that “you can schedule and run as many refreshes as required at any given time,” with the service running them “at the time scheduled as a best effort” — and each SKU carries a documented model refresh parallelism limit. Best effort with a parallelism cap means twenty models scheduled at 06:00 do not all refresh at 06:00, and the ones at the back finish whenever. Staggering schedules by dependency and importance is not tidiness; it is the difference between a stated freshness commitment and a hope.
Shared capacity means shared consequences
Enterprise BI platforms sell compute as a pool. Power BI’s documentation defines it plainly: a capacity is “a distinct pool of resources,” and “the size of the capacity determines the amount of computation power available.” Everything assigned to that pool competes for it, which makes BI capacity a design decision rather than a purchase.
What happens at the limit is documented and worth knowing before it happens. Exceed the CPU available for your SKU and the capacity “throttles its interactive operations” — the reports get slow for everyone, not for whoever caused it. There are hard ceilings elsewhere too, such as a documented 225-second limit for rendering visuals, past which they “time out and don’t display.”
One mitigation exists and it is narrower than it first appears, so check which SKU family you are on before planning around it. Autoscale adds capacity automatically when throttling starts — v-cores added “every 30 seconds, until the number of v-cores you allocated for autoscale is reached,” each remaining active “for a minimum of 24 hours” and charged to an Azure subscription. But the documentation states the limit plainly: “Autoscale is available for Power BI Premium P SKUs. Autoscale isn’t available for Fabric F SKUs.” On an F capacity the responses are different — resize the capacity, move workloads to another one, or reduce the load — and treating the P-SKU behaviour as a general safety net produces a capacity plan with an escape hatch that does not exist.
Which turns one question into the important one: what is the isolation unit, and who shares it? Putting every team on one large capacity is cheapest and means a finance month-end job can slow a customer-facing dashboard. Separate capacities cost more and contain the damage. The decision is the same one any shared platform faces, and it should be made from a stated requirement — this dashboard must respond in two seconds during business hours — rather than after the first incident.
Two operational habits follow. Monitor the pool’s utilization rather than individual report timings, because the symptom appears far from the cause. And attribute consumption to teams, since a platform whose cost nobody can attribute gets optimized by whoever is asked, which is rarely whoever is spending.
Row-level security is where a small mistake becomes a large one
Most enterprise reporting needs the same report to show different rows to different readers — a regional manager sees their region. Row-level security is the mechanism, described by Tableau as the ability to “filter data based on the user that is requesting it.” The mechanism is not the hard part; where it is enforced is.
| Where the rule lives | How it works | What can go wrong |
|---|---|---|
| In the workbook, mapping users to values by hand | An author lists who sees what | Goes stale the day someone changes role, and does not scale past a handful of names |
| In a calculated field | The filter derives the viewer’s entitlement automatically | Still per-workbook. Tableau notes that with these approaches “permissions must be secured to prevent users from seeing unfiltered data” — the rule is only as good as the permissions around it |
| In a central data policy | Enforced once, in a virtual connection, for everything that uses it | Requires the connection to be the only path to the data. Tableau’s point is that it avoids “the same risk of exposing information if an author neglects to properly secure permissions” |
| In the database | The source refuses to return rows the user may not see | Strongest and the least flexible for BI-specific slicing; needs the BI tool to pass the user’s identity through |
Before any of that, one question decides whether the rule applies at all: which permission level the reader holds. Power BI’s documentation states the boundary explicitly — RLS “only restricts data access for users with Viewer permissions. It doesn’t apply to workspace Admin, Member, or Contributor roles,” because those roles have edit permission on the model. The corollary is that a workspace where everyone is a Contributor so that anyone can fix a report has no row-level security in effect, no matter how carefully the roles were written. “If you want RLS to apply to people in a workspace, you can only assign them the Viewer role.”
Two follow-on facts are worth knowing because both are commonly assumed the other way. The restriction does survive a different client: “even if Viewers are given Build permissions to the semantic model, RLS still applies,” and a Viewer using Analyze in Excel sees filtered data. But it restricts rows only — “if a user has access to a particular row of data, they can see all the columns of data for that row,” so a sensitive column needs object-level security instead. So the review question is not “is RLS configured” but “who in this workspace is not a Viewer, and what does the rule not cover.”
The pattern across the table above is that per-workbook enforcement makes every author a security boundary. One person duplicating a workbook and forgetting to reapply the filter exposes everything — and that failure is silent, because the report renders perfectly. Central enforcement converts a repeated human step into a single configured one, which is the entire argument for it.
Whatever the mechanism, two checks belong in the routine. Enumerate every path to the data, not just the certified report: an export, a direct connection from a notebook, or a second workbook built on the same source can bypass a rule enforced only in the first one. And test as a member of each role rather than as an administrator, since least privilege is only real if someone has verified what a low-privilege account actually sees.
Self-service produces content faster than anyone retires it
The point of self-service is that people do not wait for a queue, and it works: the number of reports grows. What no tool does by default is remove any of them. Five years in, a platform holds hundreds of dashboards where a few dozen are used, several contradict each other, and the ones executives quote are not always the maintained ones.
The mechanism that helps is not a restriction on authoring. It is making the difference between a maintained report and an exploration visible, which is what content certification is for: a small set of endorsed content with a named owner, a stated definition, and a refresh commitment, and everything else clearly marked as unendorsed. Three rules make it hold.
- Certification means someone signed up for an obligation. An owner, the metric definitions it uses, a freshness target stated as an objective, and a review date. A badge without those is decoration, and readers learn to ignore it.
- Personal work stays separate from shared space. A workbook in someone’s own area cannot be mistaken for the company’s answer, and moving something into shared space is the moment to ask who owns it.
- Retirement is a scheduled activity. Usage data shows what nobody opens; the hard part is the decision, so put it on a calendar with a default of removal after notice. Reports die by attrition otherwise, which means they do not die.
Certification also depends on something upstream of the BI tool. If the certified report and an analyst’s own query disagree because the metric is defined in two places, no badge resolves it — that is the definition layer’s job, and a BI platform can only surface the answer it is given. Where reports are consumed by other teams as though they were products, the promise about definitions and freshness belongs in a data contract rather than in a shared understanding.
Ownership, and how to tell whether any of this works
Most BI trouble traces to an unowned artifact. The platform itself needs an operator — capacity, upgrades, access model — and each piece of shared content needs someone accountable for what it says. Those are different roles, and conflating them is how a platform team ends up answering questions about a definition it did not write. The owner, steward, and custodian distinction transfers directly, and the same governance question applies: who decides, and where is it written down.
Treating shared reports as a data product puts that on a familiar footing — a named owner, a stated audience, a documented definition, a support expectation — and it also makes the number of products a deliberate decision rather than a byproduct of how many people had an idea.
Four measures say whether the platform is healthy, and none of them is the report count.
- Share of viewing that happens on certified content. Rising means the endorsement is trusted; flat means readers are ignoring it.
- Ownership coverage of shared content — the BI equivalent of catalog coverage, and the one that predicts the next incident.
- Refresh reliability against the stated freshness target, not average refresh duration.
- Capacity headroom during peak hours, read as a trend rather than as an alert, because throttling arrives after the trend has been visible for weeks.
Start where the pain is loudest and the fix is cheapest: find the five reports executives actually use, give each an owner and a stated definition, and certify them. That is a week of work, and it converts the argument from “which number is right” into “who do I ask.” Everything else in this article is easier once that conversation exists.
References: Microsoft Learn, What is Power BI Premium? (documentation updated 2026-07-10); Microsoft Learn, Using Autoscale with Power BI Premium; Tableau Help, Extract Your Data; Tableau Help, Refresh Extracts; Tableau Help, Overview of Row-Level Security Options in Tableau; Microsoft Learn, Configure incremental refresh and real-time data for Power BI semantic models; Microsoft Learn, DirectQuery in Power BI; Microsoft Learn, Row-level security (RLS) with Power BI.
Discover more from Insightful Data Lab
Subscribe to get the latest posts sent to your email.
