Most Power BI headaches, sluggish refreshes, baffling filter behavior, dashboards that get opened once and never again, trace back to a handful of early decisions: how the model was built, how performance got handled once the data was loaded, how the report was laid out, and who was given access to what. This guide groups 24 practices across those four areas. None of them call for deep DAX wizardry; they mostly call for fixing things near the source instead of working around them later.
Getting the Data Model Right
The model is the foundation everything else rests on, and Power BI enforces a hard limit here: under a Pro license, a single semantic model tops out at 1GB, and going over that figure stops refreshes from completing in the Power BI Service entirely. The practices below help you stay well clear of that ceiling while also making everything built on top of the model faster.
1. Push Transformation Work as Close to the Source as Possible
A useful rule of thumb: transform data as early as you reasonably can, and only as late as you actually have to. If you're pulling from a database that accepts SQL, do as much filtering and reshaping there as you can before the data ever reaches Power Query. Without SQL access, do that work in Power Query rather than pushing it into DAX measures further down the chain. And if SQL isn't something you're confident writing, query folding, covered later in this list, can carry a lot of that load automatically.
2. Avoid Many-to-Many Relationships Wherever You Can
Many-to-many relationships are a problem on two fronts at once. For the person using the report, an extra filter applied on top of a many-to-many relationship can return results that don't match what they expected. For the model itself, visuals sitting on top of these relationships consistently render more slowly, something easy to confirm by comparing load times in the performance analyser between a one-to-many setup and a many-to-many one covering similar data volumes. The standard fix is restructuring toward a star schema so every relationship in the model ends up one-to-many.
3. Use Bi-Directional Filtering Sparingly
Bi-directional cardinality tends to show up automatically in many-to-many and one-to-one relationships, though it can also be switched on manually for an otherwise normal one-to-many relationship. The cost is real: performance drops, and filter behavior becomes genuinely difficult to predict once a model has more than one or two bi-directional relationships active at once.
For one-to-one relationships specifically, merging the two tables into a single table in Power Query is usually the cleaner move rather than keeping a bi-directional link between them. Bi-directional filtering also gets reached for when someone wants a single slicer to control every visual on a page at once; individual visual-level filters on each chart get you the same outcome without introducing a shared filtering relationship across the model.
4. Treat Data Type Selection as a Deliberate Step, Not an Afterthought
The data type assigned to a column has a measurable effect on both memory footprint and how quickly visuals render, and whatever Power BI auto-detects on import isn't always the leanest option. One specific case worth checking every time: a Date/Time column silently generates a small calendar table behind the scenes that a plain Date type does not, so switching to Date wherever the time portion isn't actually needed is close to a free performance win. More broadly, text fields cost noticeably more memory than numeric ones, so default to a numeric representation whenever your data genuinely allows it.
5. Strip Out Columns That Aren't Pulling Any Weight
It's common, especially early on, to keep every column from a source table on the theory that it might be useful eventually. In practice this is one of the more reliable ways to end up with a bloated, sluggish model. Anything not actually feeding a visual should be removed in Power Query before load rather than carried forward indefinitely. Long free-text fields deserve particular scrutiny here, since they tend to consume disproportionate memory relative to how often they actually get used.
6. Lean on Query Folding for Database Sources
Query folding hands your Power Query transformation steps back to the source system itself, so the database does the filtering and shaping and only sends back the already-processed result, rather than Power BI pulling everything raw and grinding through it locally. Most relational database connectors support this.
To confirm whether folding is actually happening on a given step, open the Power Query editor, right-click that step in the Applied Steps panel, and check whether View Native Query is available. If it is, the database is handling that step rather than Power BI. As an example, if you needed to narrow a shipment log down to orders placed after a certain warehouse came online and weighing over a set threshold, applying both conditions in Power Query and then checking for View Native Query tells you whether that filtering is genuinely happening at the database level or being pulled down unfiltered first.
7. Don't Load Staging Tables You Don't Need Loaded
Tables that exist purely to feed a merge or append step further downstream generally don't need to be loaded into the model in their own right. If three separate plant-level production logs are being combined into one consolidated table, disable load on each of the three originals and load only the combined result. Keeping all four versions loaded just multiplies the same underlying data for no real benefit.
8. Be Skeptical of Direct Query as a Default
Direct Query carries costs that are easy to underestimate until you're living with them. It limits you to a narrower set of Power Query transformations than Import mode supports, and every filter interaction or page change triggers a live round trip back to the source, which makes the report noticeably less responsive. Import mode caches the data at refresh time instead, so the report runs against a local snapshot rather than querying the source on every click. Where part of a model genuinely needs Direct Query, for real-time freshness or sheer data volume, it's usually better to leave the rest of the model on Import rather than defaulting the whole thing to Direct Query out of convenience.
9. Pre-Aggregate Wherever the Use Case Allows It
Rolling detailed records up to a coarser grain, summarizing sensor readings to an hourly average instead of keeping every individual reading, for instance, cuts both row count and overall model size substantially. Power Query's Group By feature does this cleanly across both numeric and categorical fields, and it's one of the most dependable tools available when a model has outgrown its original size.
Keeping Things Fast Once the Data Is Loaded
A clean model only solves half the problem. The rest comes down to how the report itself is built and queried once the data is sitting there.
10. Don't Default to Adding Another Visual
Every chart on a page adds to that page's total render time. Where several small visuals are showing closely related figures, a card for each region's headcount, say, consolidating them into a single table is often both faster to load and easier to scan than the same information spread across separate tiles.
11. Cut Slicers That Aren't Earning Their Place
Each slicer on a page fires two separate queries under the hood, one to populate its own list of selectable values and a second to apply the resulting filter everywhere else. A page carrying several slicers that nobody actually uses to filter anything meaningful is paying a real performance cost for essentially nothing, so it's worth auditing a page's slicers periodically and removing the ones that aren't doing real work.
12. Reach for Native Visuals Before Marketplace Ones
Power BI's built-in visual types are optimized in ways most third-party visuals from the marketplace simply aren't. If a native visual can be coaxed into doing what you need, even if that takes a more elaborate DAX measure to pull off, it will typically still outperform a custom visual built to do the same job out of the box.
13. Find and Fix Your Worst-Performing DAX
The performance analyser shows exactly how long each visual's underlying query takes, which makes it easy to spot the small number of measures actually dragging on load time rather than guessing. Row-by-row iterator functions, SUMX, AVERAGEX, COUNTX, and their relatives, are a frequent offender, since they evaluate one row at a time instead of operating across an entire column at once. When an iterator is unavoidable, point it at the smallest table available and avoid nesting one inside another. Storing intermediate results in variables within a DAX expression also tends to cut down on repeated, redundant calculation.
14. Upgrade the Hardware When That's the Actual Constraint
If a report runs Direct Query against a SQL Server instance, query speed is tied directly to that database's compute tier, its DTU or vCore allocation, so increasing that tier can produce a real, measurable speedup. The same logic carries over to any on-premises data gateway sitting in the path: more memory and CPU on that gateway machine shortens refresh times for anything routed through it.
15. Tune the Data Gateway Rather Than Leaving It on Defaults
By default, a gateway pulls data from the source, then processes and compresses it for the model, one step after the other. Turning on the Stream Before Request Completes setting lets these stages overlap instead of waiting on each other in sequence, which shortens the overall refresh window. It's also worth excluding the gateway's working directories from live antivirus scanning, since that scanning can noticeably slow down large file operations mid-refresh.
Designing Reports People Actually Want to Open
A well-built model and a fast refresh don't count for much if the resulting report is confusing or exhausting to look at. Design is usually what decides whether a report gets used regularly or opened once out of curiosity and forgotten.
16. Apply Established Visual Grouping Principles
The Gestalt principles, proximity, similarity, continuity, closure, enclosure, symmetry, and figure-ground, describe how people naturally group and read visual information without being told to. None of this is specific to Power BI, but applying it consistently is usually the difference between a report that explains itself and one that needs a walkthrough every time someone new opens it.
17. Choose the Chart That Fits the Question Being Asked
The right chart type makes a pattern jump out; the wrong one buries it under formatting. Before reaching for whatever visual is quickest to drop onto the canvas, pause and consider what kind of comparison you're actually trying to surface, a trend over time, a part-to-whole breakdown, a ranking, and pick the chart built for that specific job.
18. Lay Out the Page in the Order People Actually Scan It
Eye-tracking studies on dashboards consistently show people scanning in a rough F-shaped pattern: heaviest attention in the upper-left, tapering off moving right and down the page. Put the figures that matter most, headline KPIs and summary totals, in that upper-left zone, and push detailed, drill-capable tables toward the lower-right, where they'll get a closer look only from someone already engaged enough to dig further.
19. Remove Formatting That Isn't Doing Any Work
Default axis titles nobody reads, redundant data labels, and busy gridlines all add up to visual noise competing with the actual numbers for attention. Go through each visual on a page and ask whether a given formatting element is genuinely informative or just present by default, then strip out whatever falls into the second category.
20. Let the Layout Breathe
Cramming visuals edge to edge makes a page feel dense and harder to absorb, even when the underlying numbers haven't changed at all. Deliberate white space functions a lot like a pause in conversation, it gives the person looking at the page room to process one section before their eyes move to the next, rather than asking them to take everything in all at once.
21. Choose Color With Intent, Not by Whatever the Theme Defaults To
People bring color associations into a report whether or not you meant to trigger them, green tends to read as favorable, red as a warning, almost automatically. Rather than letting a default theme assign colors arbitrarily across categories, choose colors so they reinforce what the data is actually saying, instead of accidentally sending a signal that contradicts it.
Keeping Sensitive Data Where It Belongs
None of the performance or design work matters if the wrong person can open the report and see data they were never meant to see.
22. Use Row-Level Security Instead of Maintaining Parallel Reports
Row-level security lets a single published report serve several different audiences by filtering the underlying data according to who's actually viewing it, rather than maintaining a separate near-identical copy of the report for each team. A branch manager sees only their branch's figures; a regional director sees every branch under them, all from one shared report rather than several maintained in parallel.
23. Keep Workspace Access on a Tight Leash
Default to least privilege: give each person only the access their actual role requires and nothing beyond that. This one habit closes off a large share of the ways sensitive datasets end up visible to people who were never supposed to have that access in the first place.
24. Label Sensitive Assets and Keep an Eye on Activity
Workspace admins can apply sensitivity labels to datasets and dashboards so that anyone browsing a workspace can immediately see which assets are confidential and shouldn't be exported or forwarded casually. For data that legally or contractually can't leave your own infrastructure, Power BI Report Server offers an on-premises alternative that keeps all processing local rather than routing through the cloud service. And for whatever does live in the cloud, the activity reports available to admins are worth a periodic look, since unusual access patterns or unexpected sharing tend to surface there well before they surface anywhere else.
Bringing It Together
None of these 24 practices demand starting over. Most can be layered onto an existing report gradually: get the data model in shape first, since everything else depends on it, then work through performance, then layout, then access. Reports built with this kind of discipline from day one tend to stay fast and genuinely usable as they grow, instead of quietly accumulating the kind of technical debt that eventually forces a full rebuild anyway.
