top of page

Slow DAX: The 7 Measure Mistakes Quietly Strangling Your Reports

  • Writer: Matt Lazarus
    Matt Lazarus
  • 10 minutes ago
  • 5 min read
Isometric illustration of a dashboard panel held back by seven tangled cables, one being cleanly cut by a beam of light as the panel lifts.
Spinning visuals are usually seven DAX mistakes in a trench coat.

The report is correct, the model refreshes, and every visual takes thirty seconds. Users have learned to click and check their phone - which means users have learned to stop exploring, which means the report is failing at the only job that matters.

 

Slow visuals are almost never a data-volume problem and almost always a measure-writing problem: the same business logic can run in milliseconds or minutes depending on whether it lets the storage engine work or forces the formula engine to grind. Seven mistakes account for the vast majority of the grinding.

 

Here they are, each with its fix - plus the ten-minute diagnostic that tells you which one you have.

 

Key Takeaways

 

  • Slow DAX is a pattern problem, not a data problem - the same logic written engine-friendly runs orders of magnitude faster.

  • Seven mistakes cause most of it - iterators, FILTER misuse, column abuse, bi-directional traps, context transition, missing variables, over-nesting.

  • Diagnose before rewriting: Performance Analyzer isolates the visual; DAX Studio attributes the time.

 

Why Does Speed Decide Whether Reports Get Used?

 

Because interaction is the product. A visual that answers in under a second invites the next question; one that answers in thirty trains users to stop asking. Performance is an adoption problem before it is a technical one - the slow report is abandoned long before anyone files a ticket about it.

 

The engine context in one paragraph: DAX queries are served by two engines - a storage engine that scans compressed columns at extraordinary speed, and a formula engine that handles logic the storage engine cannot. Fast DAX keeps the work in the storage engine; the seven mistakes all, in different ways, drag it into the formula engine row by row.

 

What Are the Seven Mistakes?

 

Each is recognisable on sight once named, and each has a mechanical fix.

 

  • 1. Iterators over full tables. SUMX over millions of fact rows computing what a column multiplication and SUM could express - or worse, nested iterators multiplying the row count. Fix: pre-compute row-grain arithmetic upstream, keep iterators to small tables.

  • 2. FILTER(Table) inside CALCULATE where a predicate would do. CALCULATE([Sales], FILTER(Sales, Sales[Region]="NSW")) materialises the table in the formula engine; CALCULATE([Sales], Sales[Region]="NSW") becomes a storage-engine filter. Same number, different decade.

  • 3. Calculated columns doing measure work. Row-level ratios and flags computed and stored on big tables bloat the model and still aggregate wrongly. Fix: measures for context-dependent maths, Power Query or the source for genuine shape.

  • 4. Bi-directional relationships as a convenience. Both-directions filtering set to make one visual work makes every query pay ambiguity costs and invites circular filter paths. Fix: single direction by default, CROSSFILTER inside the specific measure that needs it.

  • 5. Context transition in the wrong place. Measures referenced inside row-by-row iterations quietly invoke CALCULATE per row - thousands of context transitions per visual. The innocent-looking SUMX(Customers, [Total Sales]) pattern is this mistake wearing a suit.

  • 6. No variables, repeated work. The same expression evaluated three times in one measure (value, comparison, display) triples the cost. VAR computes once; RETURN reuses.

  • 7. Over-nested heroics. Five-deep nested logic that nobody can read is also logic the optimiser cannot help - and the next analyst's reason to copy-paste rather than reuse. Fix: base measures composed into clear layers.

 

Isometric split engine room: one machine grinding row by row, the other a sleek columnar engine scanning slim columns instantly.
Write measures the engine can scan by column, not iterate row by row.

How Do You Find Which Mistake You Have?

 

Performance Analyzer first: record an interaction, sort by duration, and the offending visual identifies itself - along with whether the time sits in the DAX query or in visual rendering. One slow visual is a measure problem; everything slow equally is usually the model's shape.

 

Then DAX Studio for attribution: paste the captured query, run with server timings, and read the split between storage engine and formula engine. Heavy formula-engine time with low storage-engine parallelism is the signature of mistakes one, two and five; a storage engine scanning vastly more data than the visual needs points at the model or mistake four. The workflow takes ten minutes and replaces guesswork with a named culprit - the difference between optimising and rewriting things at random.

 

What Do the Fixes Look Like in Practice?

 

Mechanical, mostly - which is the encouraging part. The FILTER-to-predicate rewrite is a one-line change; variables are syntax; iterator removal is usually one pre-computed column upstream and a simpler measure. The deeper fixes - retiring calculated columns from the fact table, straightening bi-directional relationships - take a careful afternoon each with reconciliation checks after.

 

Real engagements routinely take a visual from thirty-plus seconds to under one without changing a single number on screen - the logic was always right; it was the engine's path to it that was wrong. That is the standard arc of a Power BI performance optimisation: measure, attribute, rewrite the patterns, reconcile, and hand back the same report at interactive speed.

 

How Do You Stop the Mistakes Coming Back?

 

Standards plus review. A one-page measure standard - predicates over FILTER, variables always, iterators justified, base-measure composition - costs nothing and prevents most regressions; a peer review of measures before anything ships to a shared workspace catches the rest. The seven mistakes are habits, and habits respond to checklists.

 

For estates without a resident DAX specialist, periodic health checks serve the same function: a quarterly pass over the highest-traffic models, profiling the top visuals and reviewing new measures against the standard. It is a standing line item in most managed services retainers precisely because performance decays socially - every new measure written under deadline pressure is a candidate regression, and someone has to be looking.

 

When Should You Stop Tuning Measures and Restructure the Model?

 

When the same class of fix keeps recurring, the measures are no longer the problem. Three signals make the call clear: every slow measure traverses the same bloated table or snowflaked relationship chain; fixes speed up one visual while others degrade; and new measures are born slow no matter who writes them. Tuning at that point is bailing a boat with a structural leak.

 

The economics favour the rebuild sooner than teams expect. A week of measure surgery that buys two seconds is a worse investment than two weeks of remodelling that makes the whole report instant and every future measure cheap to write - because model shape is leverage, applied to everything built on it, while measure fixes are interest payments on the shape you kept.

 

The practical threshold: once three or more of the seven mistakes trace back to model structure rather than DAX style, schedule the remodel and stop polishing. The fastest DAX in the world cannot outrun a shape that forces it to do the storage engine's job.

 

The restructure conversation is also where the budget argument is easiest to win: stakeholders who would never fund "model refactoring" will readily fund "every report under three seconds", even though they are the same project. Frame the work by the experience it buys, not the engineering it involves.

 

Same Numbers, Different Experience

 

Nothing in this article changes a single figure on a single report - and that is the point. The numbers were never the problem; the path the engine took to them was. Name the seven mistakes, run the ten-minute diagnostic, and rewrite the patterns: the report your users abandoned at thirty seconds becomes the report they explore at one.

 

Speed is not polish. It is whether the questions get asked at all.

 
 
bottom of page