There's a measure in your model that nobody wants to touch. It has three nested CALCULATE calls, repeats the same sales expression in four places and, when you drop it into a visual, the report hesitates before it draws. When someone asks what it actually does, the honest answer is usually: "it works, don't touch it." That's the portrait of a measure written without variables.
DAX variables — declared with VAR and returned with RETURN — are among the simplest and most underused tools in Power BI. The idea is elementary: compute a value (or a table) once, give it a name and reuse it as many times as you need. The effect is anything but elementary: faster measures, easier to read and far less painful to fix when something goes wrong.
This guide shows what DAX variables are, why they improve performance, how to use them well and which pitfalls to avoid. By the end you'll have a pattern that applies to almost any measure in your report — from a margin calculation to the most convoluted indicator on the dashboard.
What a DAX variable actually is
A variable stores the result of an expression so you can reuse it later by name. You declare it with VAR, followed by a name and the expression; the measure's final value comes after RETURN. A measure can have several VAR declarations, but only one RETURN.

A simple profit-margin example:
Margem % =
VAR Vendas = SUM ( Faturas[Total] )
VAR Custo = SUM ( Faturas[Custo] )
VAR Lucro = Vendas - Custo
RETURN
DIVIDE ( Lucro, Vendas )
Notice how each step has a name. You don't need to decode what SUM ( Faturas[Total] ) means three lines down: it's Vendas. The expression reads almost like a sentence, and that alone makes variables valuable before we even mention performance.
Why they make measures faster
The golden rule is this: a variable is evaluated only once, and the result is stored for every later use. When you write SUM ( Faturas[Total] ) in three places within a measure, you're potentially asking the engine to do that calculation three times. Store it in a variable and the work is done once and reused.
In small models the difference is imperceptible. In tables with millions of rows, or in measures that iterate with SUMX over the detail, avoiding repeated recomputation can turn a sluggish visual into an instant one. Variables aren't an exotic micro-optimization trick: they are often the cheapest way to speed up a report.
More readable code: less repetition, more intent
Readability isn't an aesthetic luxury. A measure you understand is a measure you can audit, fix and evolve without fear. Variables let you break a complex calculation into named steps, each documenting its own intent.
Compare a nested expression crammed into a single line with the step-by-step version. The first forces you to read from the inside out and hold intermediate values in your head. The second tells you, line by line, what is happening. Six months from now — or when someone else opens the file — that clarity is worth its weight in gold.
Debugging measures by peeking at variables
There's a debugging trick that alone justifies adopting variables. When a measure returns something strange, temporarily change the RETURN to output one of the intermediate variables instead of the final result:
Margem % =
VAR Vendas = SUM ( Faturas[Total] )
VAR Custo = SUM ( Faturas[Custo] )
VAR Lucro = Vendas - Custo
RETURN
Lucro
Put that measure in a card, check whether Lucro holds the expected value and, once you find the error, restore the original RETURN. Without variables you'd have to split the formula into throwaway measures just to inspect the steps. With them, the diagnosis happens right where the logic lives.
Variables that hold tables, not just numbers
A variable doesn't have to be a number. It can hold an entire table — the result of a FILTER, for instance — and reuse it later. This opens the door to more expressive measures without repeating the filtering logic:
Clientes Ativos Alto Valor =
VAR Selecao =
FILTER (
Clientes,
Clientes[Estado] = "Ativo" && Clientes[Valor] > 1000
)
RETURN
COUNTROWS ( Selecao )
The Selecao variable is an in-memory table. You could count it, sum over it or use it as a filter inside CALCULATE — all from the same definition, written once.
The context trap: where the variable is evaluated
Here's the point that catches almost everyone. A variable is evaluated in the context where it is declared, not where it is used. If you declare a variable outside a CALCULATE and then use it inside, it keeps the value it had before CALCULATE changed the filter context.
Often this is exactly what you want — it lets you, for example, compare the current value with a value "frozen" before the context change. But if you expected the variable to "react" to the new filter, you'll get a result that looks wrong. It isn't a DAX bug; it's the rule doing its job. Whenever something doesn't add up inside a CALCULATE, always ask yourself in which context the variable was actually evaluated.
Common mistakes to avoid
- Vague names.
Temp1,AuxorXthrow away half the benefit. Give names that say what the value represents:Vendas,Lucro,ClientesAtivos. - Expecting a reaction to changed context. As we saw, a variable doesn't "see" the filter a
CALCULATEapplies after it was declared. - Trying to return two things. There is only one
RETURN. If you need two results, either write two measures or return a table. - Declaring without using. A variable that never reaches the
RETURNor another variable is noise — the engine may ignore it, but the person reading the code won't. - Assuming variables are shared between measures. Each measure has its own scope; a
VARcalledVendasin one measure has nothing to do with another of the same name elsewhere.
Mini-case: a sales dashboard that could breathe again
A B2B distribution company had a sales dashboard with about thirty measures. Several repeated the same SUMX over the invoice-line table — more than two million records — to calculate revenue, margin and average ticket. The main page took close to nine seconds to render, and newer analysts avoided changing anything for fear of breaking something.
The team rewrote eight critical measures, moving the repeated calculations into variables at the top of each formula. They didn't change the model or add hardware. Page load time dropped to around three seconds and, just as important, a junior analyst was able to understand and adjust the measures without help. Readability turned an untouchable corner of the report into code the team could maintain with confidence.
In practice
Adopt variables by default, not as an advanced technique reserved for experts. Two practical rules solve almost everything: if you repeat an expression, turn it into a variable; if a measure runs past three or four lines, it probably reads better with VAR. You give clear names to the steps, evaluate each expression only once and gain a debugging method for free. It is, at heart, basic DAX hygiene — and the kind that pays back the most per minute invested.