← Back to Blog

Top 10 DAX Anti-Patterns (and How to Fix Them)

Why Anti-Patterns Matter

Every Power BI model accumulates technical debt over time. DAX measures written under deadline pressure often contain patterns that hurt performance, readability, and maintainability. We analyzed hundreds of models and identified the 10 most common anti-patterns.

1. Bare Division (No DIVIDE)

Using / instead of DIVIDE() is the single most common anti-pattern. When the denominator is zero, bare division returns Infinity — causing visual errors and confusing end users.

// ❌ Bad
Sales Margin = [Revenue] - [Cost]) / [Revenue]

// ✅ Good
Sales Margin = DIVIDE([Revenue] - [Cost], [Revenue])

Why it matters: DIVIDE() gracefully returns BLANK() on zero denominators, preventing "Infinity" from appearing in your reports.

2. Nested CALCULATE

Multiple CALCULATE() calls nested inside each other create confusing filter context transitions. Each CALCULATE resets the filter context, making behavior hard to predict.

// ❌ Bad
CALCULATE(
    CALCULATE(SUM(Sales[Amount]), Sales[Region] = "US"),
    DATESYTD('Date'[Date])
)

// ✅ Better — combine filters in a single CALCULATE
CALCULATE(
    SUM(Sales[Amount]),
    Sales[Region] = "US",
    DATESYTD('Date'[Date])
)

3. SUMX Over Full Table

Using SUMX(table, expression) without filtering the table first iterates over every row — potentially millions of rows for a calculation that could be a simple SUM.

4. No VAR in Complex Measures

Repeating the same sub-expression multiple times in a measure is both a performance hit (evaluated multiple times) and a readability problem. VAR/RETURN is the fix.

// ❌ Bad — [Total Sales] evaluated twice
IF([Total Sales] > 1000, [Total Sales] * 0.1, 0)

// ✅ Good
VAR _sales = [Total Sales]
RETURN IF(_sales > 1000, _sales * 0.1, 0)

5. EARLIER Instead of VAR

EARLIER() is a legacy function from before VAR was introduced. It's harder to read and understand. Always use VAR instead.

6. Calculated Columns That Should Be Measures

Calculated columns are computed at refresh time and stored in memory. If the calculation doesn't need row context, it should be a measure — computed at query time with no storage cost.

7. Unused Measures

Dead code in your model adds confusion and makes maintenance harder. Regular audits should identify and remove measures that aren't referenced by any visual.

8. Missing Format Strings

Measures without explicit format strings rely on inherited formatting, which can produce inconsistent results across different visuals.

9. Long Measures Without Comments

Measures over 10 lines that lack comments are a maintenance nightmare. The original author might understand them, but nobody else will — including the original author 6 months later.

10. Star Schema Violations

Many-to-many relationships, bi-directional filters, and missing dimension tables all violate star schema best practices and cause unpredictable filter behavior.

Automate Your Audit

DaxAudit checks for all 10 of these anti-patterns (plus 21 more) automatically. Upload your model and get results in under 60 seconds.

Ready to audit your model?

Upload your .pbix or .pbit and get an instant health check — free, no account needed.

Try DaxAudit →