Introduction
We have lost count of how many Power BI models we have opened over the years where the refresh takes twenty minutes, the file is bloated past a gigabyte, and nobody on the client's team can tell us why. Nine times out of ten, the answer sits in the same place. Somebody built calculated columns for logic that should have been pushed back to the source, or somebody wrote a Power Query step that quietly broke query folding without anyone noticing.
This is one of those topics that sounds technical and slightly dry until you realise it is the actual difference between a report that opens in two seconds and one that makes your finance team sit and stare at a spinning circle every Monday morning. We work on Power BI models for finance teams, operations teams, and leadership dashboards across manufacturing, healthcare, retail, and SaaS businesses, and this exact question comes up on almost every engagement: should this be handled in Power Query, where it can fold back to the source, or should it be a calculated column inside the model?
In this guide, we are going to walk through what query folding really is, what a calculated column actually does under the hood, and where each one genuinely earns its place in a Power BI build. We will also share a comparison table, the mistakes we see most often in client models, and a checklist you can run through before your next build. Our goal is not to make this sound more complicated than it is. It is to give you a clear, practical answer so you stop guessing and start building models that hold up as your data grows.
What Query Folding Really Means
Query folding is what happens when Power BI takes the steps you build in Power Query and translates them back into a query that runs on the original data source, instead of pulling every row into Power BI first and doing the work locally. If your source is a SQL Server database, a filter step you add in Power Query gets converted into a WHERE clause. A group by step becomes a GROUP BY. A join becomes a proper SQL join. All of that work happens on the server that holds the data, and Power BI only receives the result.
The benefit is straightforward. Databases are built and indexed to filter, sort, and aggregate large volumes of data quickly. Power BI is not a database engine in the same sense, so asking it to pull ten million rows across the wire and then filter them down to fifty thousand is simply wasteful. When folding works, you get a smaller, faster, cleaner data pull, and your refresh times stay reasonable even as the underlying tables grow.
Not every step folds. Custom M functions, certain merges between sources that do not share a connection type, adding an index column, and some text transformations will break the fold at the point they are introduced. Once folding breaks, every step after that point runs locally inside Power BI's engine rather than on the source, and you lose the performance advantage from that step onward. This is why the order of your Power Query steps matters just as much as the steps themselves. We always try to place foldable steps such as filters, column removals, and type changes as early as possible, and push anything that will break folding, like a custom function, as late as possible in the query.
You can check whether a step folds by right clicking it in the Applied Steps pane and looking at whether "View Native Query" is available. If it is greyed out, folding has stopped at that step. This one habit alone has saved us hours of debugging on client projects where a refresh mysteriously slowed down after what looked like a harmless change.
It is also worth remembering that folding is not an all or nothing switch for the whole query. It is evaluated step by step. A query can fold perfectly for its first six steps, then hit a custom column formula on step seven and stop folding from that point forward. Everything before step seven still ran on the source and benefited from folding. Everything from step seven onward ran locally in Power BI's own engine, using your local machine's memory and processing power during a desktop refresh, or the capacity allocated to your workspace during a service based refresh. Understanding this step by step nature is what lets you make small, deliberate trade offs rather than treating the whole query as either fast or slow.
We touched on some of this when we wrote about how Power BI fuels rapid business expansion, where a slow, poorly folded model was one of the biggest blockers we saw in fast growing companies trying to scale their reporting.
Not Every Source Supports Folding the Same Way
One detail we find catches teams off guard is that folding is not a Power BI feature so much as a connector feature. Whether a step folds depends on whether the connector you are using has been built to translate Power Query steps into a query language the source understands. Structured sources such as SQL Server, Azure SQL, PostgreSQL, Snowflake, and most modern data warehouses fold well, because their connectors were designed with folding in mind and they speak a query language, usually SQL, that maps cleanly onto Power Query's own step logic.
File based sources behave differently. A folder of CSV files, a single Excel workbook, or a flat text export does not have a query engine sitting behind it, so there is nothing for Power BI to fold back to. Every transformation you apply to a file based source runs locally, inside Power BI, regardless of how well you order your steps. This is one of the biggest reasons we encourage clients to move away from spreadsheet based reporting sources whenever a proper database or a data warehouse is available. It is not just about accuracy or version control, although both matter. It is that a spreadsheet source removes query folding as an option entirely, and every ounce of transformation work then falls on the Power BI engine and on the calculated columns and measures built inside the model.
APIs sit somewhere in the middle. Some API connectors support parameterised requests that behave a little like folding, where filters get passed into the request itself rather than pulling the full dataset and filtering afterward. Others do not, and every record comes back regardless of what you actually need. When we scope an integration, whether it is a NetSuite connection, a Salesforce pull, or a custom internal API, we always test this early, because it changes how we design the entire extraction layer.
For clients pulling from NetSuite specifically, we have gone into more depth on this in our NetSuite Analytics Warehouse overview, which covers how the underlying data structure affects what can be folded and what ends up needing to be handled downstream instead.
What a Calculated Column Really Does
A calculated column is a column you define inside the Power BI data model using DAX, after the data has already been loaded. It is computed once per row, at the time of refresh, and the result is stored physically in the model, becoming part of the table just like any other column that came from the source.
Because it is calculated using DAX and evaluated in row context, a calculated column can do things Power Query and SQL cannot always do as cleanly. It can reference other columns in the same row, use relationships to pull values from related tables through functions like RELATED, and apply logic that depends on the position of a row within its own table. Concatenating a customer's first and last name, flagging a transaction as "Late" based on a date comparison within the same row, or building a custom sort key are all classic, sensible uses of a calculated column.
The cost is that every calculated column becomes a permanent, stored part of every row in that table, for as long as the model exists. On a small dimension table with a few hundred rows, this is not something you will ever notice. On a fact table with fifty million rows, adding a handful of calculated columns can meaningfully increase the size of the .pbix file, slow down the VertiPaq compression the engine relies on for speed, and add processing time to every single refresh, whether that refresh runs on your desktop or on a scheduled job in the Power BI service.
It is worth being clear that a calculated column is not the same thing as a measure. A measure is calculated at query time, only for the specific context a visual asks for, and it is never stored on disk. A calculated column is stored, row by row, whether or not anyone ever looks at it in a report. That distinction is at the heart of most of the performance conversations we have with clients.
The Fundamental Difference: Where the Work Happens
Strip away the terminology and this whole topic comes down to one question. Where do you want the computer to do the work?
Query folding pushes the work upstream, to the source system, before the data ever reaches Power BI. A calculated column keeps the work downstream, inside the Power BI model itself, after the data has already arrived. Neither approach is universally right. The correct choice depends on what the source system can express, what the logic actually needs, and how large the table is going to get.
A useful way we explain this to clients is to think about a factory. Query folding is like asking your supplier to pre-cut the materials to size before they ship them to you. Less material moves, less handling happens on your floor, and your own production line runs faster. A calculated column is like receiving the raw materials and doing the cutting yourself, on site, every single time a new batch arrives. Sometimes that is genuinely necessary, because the cut depends on something only you know once the materials are in front of you. But if the supplier could have done it just as easily, shipping the raw block every time and re-cutting it on your floor is wasted effort that compounds with every batch.
This is really a modeling decision, not a technical trick. The businesses that get the most value out of Power BI are the ones where the modeler thought carefully about where each piece of logic belongs before writing a single line of DAX or M.
There is also a compression angle that often gets missed. Power BI's VertiPaq engine compresses columns individually, and it does this best on columns with fewer distinct values and a predictable pattern. Data pulled cleanly through a folded query tends to compress well, because it arrives already shaped close to how it will be used. Calculated columns, especially ones built from concatenation or conditional logic that produces many unique text values, often compress poorly by comparison. That is part of why a handful of calculated columns on a large fact table can add a surprising amount to your file size, even when the logic itself looks simple on paper.
Query Folding vs Calculated Column at a Glance
Here is a side by side comparison we use internally when we are training new analysts on our team. It is the same framework we walk clients through during a Power BI health check.
| Factor | Query Folding | Calculated Column |
|---|---|---|
| Where it runs | On the source system, before the data lands in Power BI | Inside the Power BI data model, after the data has loaded |
| Engine used | The source database engine, using SQL or an equivalent query language | The VertiPaq engine, using DAX |
| Effect on file size | None. It reduces rows and columns before they arrive, so the model stays lighter | Adds a new column to every row in the table, which increases the size of the .pbix file |
| Refresh performance | Usually faster, because the source database does the filtering and aggregation | Calculated during every refresh, which adds processing time as row counts grow |
| Best suited for | Filtering, joins, grouping, and transformations that a relational source can express in SQL | Row context logic, text concatenation, and calculations that depend on relationships within the model |
| Common failure point | Custom M functions, merges across unrelated sources, or certain Power Query steps that break the fold | Overuse across large fact tables, which quietly inflates model size and slows refresh |
When Query Folding Is the Right Choice
Query folding is almost always the right call when your source is a relational database and the transformation is something SQL can express cleanly. This covers a large share of the transformations analysts do every day.
- Filtering rows, such as pulling only the last three fiscal years or only active customer accounts
- Removing or renaming columns you do not need in the model
- Joining or merging tables that share the same connection type and live on the same source
- Grouping and aggregating data before it lands in Power BI, such as summarising daily transactions into monthly totals
- Changing data types early, before other transformations are applied
If your source table has millions of rows and you only need a filtered slice of it, folding that filter back to the source means Power BI never has to move or store the rows you did not need in the first place. This is the single biggest lever for refresh performance on large fact tables, and it is the reason we always start a Power BI build by reviewing the source connection and confirming what does and does not fold before we touch a single visual.
When a Calculated Column Actually Makes Sense
A calculated column earns its place when the logic genuinely depends on row context inside the model, on relationships between tables that only exist once the model is loaded, or on something the source system simply cannot compute.
- Creating a custom sort order for a column, such as sorting month names in calendar order rather than alphabetically
- Flagging or bucketing rows based on values from a related table using RELATED, where that relationship only exists inside the Power BI model
- Building a composite key for relationships when the source does not already provide one
- Concatenating text fields for display purposes on a small dimension table
- Logic that must be evaluated at the granularity of a single row and needs to persist across every visual, rather than changing with filter context
Note that most of these examples involve smaller dimension tables, such as a product list, a calendar table, or a customer list, rather than large fact tables. That is not a coincidence. The row count of the table you are adding the column to is one of the biggest factors in whether a calculated column is a sensible choice or a slow one. A calculated column on a five thousand row product table costs almost nothing. The same logic on a forty million row transaction table is a different conversation entirely, and in most cases we would rather push that logic back into Power Query, into the source SQL, or handle it with a measure instead.
Common Mistakes We See in Client Power BI Models
When we run a Power BI health check for a new client, the same handful of issues show up again and again. We are sharing them here because they are avoidable, and because catching them early saves real money on compute and real hours of frustration for whoever owns the report.
- Building a calculated column for something that could have been a measure, which means it is stored and recalculated on every refresh instead of being computed only when a visual actually needs it
- Adding a custom column or a merge step early in a Power Query flow, which silently breaks folding for every step that follows it, even ones that would otherwise have folded fine
- Using calculated columns on the largest fact table in the model to solve a problem that a simple filter or a query at the source could have handled
- Not checking "View Native Query" during development, so folding breaks months before anyone notices and by then nobody remembers which step caused it
- Duplicating the same calculated column logic across several tables instead of solving it once, upstream, where every table can reference the same clean value
- Connecting to a source through a driver or connector that does not support folding at all, then wondering why every transformation runs slowly no matter how the query is written
None of these are exotic problems. They are the kind of thing that creeps in when a report is built under a deadline and nobody goes back to clean up the model once it is live. This is exactly the gap our Power BI Support Services and ongoing managed engagements are built to close, because a model that was fast on day one does not always stay fast as the data grows, unless somebody is watching it.
We saw a version of this play out when we put together our piece on Power BI executive dashboard examples for leadership and CEOs. A few of those dashboards looked polished on the surface but were quietly sitting on top of models weighed down by calculated columns that should have been folded upstream months earlier.
How We Approach This at Versich
When our team scopes a Power BI Development or Power BI Consulting engagement, model architecture is one of the first things we look at, before we design a single dashboard. We ask what the source system is, whether it supports folding, and how large each table is expected to get over the next two to three years, not just today. That forward looking view matters, because a model that performs fine at ten thousand rows can slow to a crawl at ten million, and the fix is much cheaper before a hundred reports are already built on top of it.
Our approach usually looks like this. We push as much transformation as possible back to the source through folded Power Query steps or through views built directly in the source database. We reserve calculated columns for logic that genuinely needs row context or relationship awareness inside the model, and we keep them off the largest fact tables wherever we can. Where a client already has an existing model, our Power BI Support Services engagements often start with exactly the kind of audit we described above, tracing every calculated column and every Power Query step to understand where the model is spending its time.
We also work closely with clients whose Power BI models sit on top of NetSuite, and our NetSuite and Power BI Integration Services are built with this exact folding question in mind, because the way data is extracted from NetSuite has a direct impact on how well it folds once it reaches Power Query. Getting that extraction layer right the first time avoids a lot of the calculated column workarounds we see in models where the source connection was never properly optimised.
If your team is trying to decide whether to bring in a Power BI Consultant for the strategy side of this or hire a Power BI Developer for the hands on build, we would say most of our best engagements involve a bit of both. Strategy without technical execution stays theoretical, and execution without strategy tends to repeat the same mistakes at a larger scale.
A Quick Checklist Before You Build
Before your next Power BI build, or before you add your next calculated column to an existing model, run through this short list. We keep a version of this pinned above every analyst's desk on our team, and it is the same thinking behind the templates in our Power BI project management dashboards guide, where a clean model underneath is what made those dashboards usable at scale.
- Confirm whether your source connector supports query folding at all, since some connectors and some on premises drivers never will
- Order your Power Query steps so filters, column removals, and type changes happen early, and anything that breaks folding happens as late as possible
- Check "View Native Query" after every new step during development, not just once at the end
- Ask whether the logic you need could be a measure before you build it as a calculated column
- Keep calculated columns off your largest fact tables unless there is genuinely no other way to express the logic
- Push repeated logic upstream, into a source view or an early Power Query step, instead of repeating a calculated column across multiple tables
- Revisit the model every few months as row counts grow, since a decision that made sense at launch may not make sense a year later
Conclusion
Query folding and calculated columns are not competing techniques. They are two different tools that solve different problems, and the skill in building a good Power BI model is knowing which one to reach for and when. Push what you can back to the source, so the database does the heavy lifting it was built to do. Keep calculated columns for the logic that genuinely needs to live inside the model, and be honest with yourself about the cost they add as your tables grow.
We have rebuilt enough Power BI models from the ground up to know that the businesses getting the most value from their data are rarely the ones with the flashiest dashboards. They are the ones whose models were built with this kind of thinking from the start, where refresh times stay predictable and reports stay usable as the business scales. If you would like a second opinion on how your own model is built, or if you are starting a new Power BI project and want it built the right way the first time, we would like to hear from you.
Ready to talk through your own model? Contact us and we will walk you through what we find, no pressure, no jargon, just a clear picture of where your Power BI build stands today.

