← All articles
Direct LakeFabric

Import vs. DirectQuery vs. Direct Lake

potphodepraful

PowerBI consultant ·

Three different answers to "where does the data live?"

These three storage modes aren't three flavors of the same thing — they answer a completely different question about where your data physically sits when a report queries it.

Import

Import mode copies data out of the source and compresses it into VertiPaq, Power BI's in-memory columnar engine. Every visual queries that in-memory copy, not the original source, which is why Import models are almost always the fastest. The cost is freshness: data is only as current as the last scheduled refresh, and a large fact table can push you against dataset size limits or refresh-time limits.

DirectQuery

DirectQuery stores nothing. Every visual interaction generates a query — usually SQL — sent live to the source, and the result comes straight back with no VertiPaq cache in between. Data is always current to the second, but performance now depends entirely on the source: its indexing, its concurrency limits, its own load at that moment. Certain DAX functions and time-intelligence patterns either don't push down cleanly or are disabled outright, because not every DAX construct has a sensible SQL translation.

Direct Lake

Direct Lake is Fabric-specific, and it's not a compromise between the other two so much as a different mechanism entirely. Instead of a scheduled refresh copying rows into VertiPaq, Direct Lake reads Parquet files straight from OneLake and builds VertiPaq-style column segments in memory at query time, on demand. When those segments are already resident, performance looks like Import. When they're not — or when the engine hits a condition it can't serve directly — it falls back to DirectQuery, silently, with DirectQuery's performance profile and none of the warning a developer might expect.

The fallback triggers that catch people out most often:

  • Row-level security with complex DAX in the RLS filter can force a fallback for the tables involved.
  • Calculated columns and calculated tables aren't supported in Direct Lake and push the whole table to DirectQuery.
  • Schema drift between the OneLake table and the semantic model — a column renamed or dropped upstream — breaks the mapping.

Picking one

Default to Import unless you have a specific reason not to — it's still the most predictable and the best-supported by the full DAX surface. Reach for DirectQuery when near-real-time freshness genuinely matters more than query speed, and the source can handle the concurrent load. Reach for Direct Lake when the data already lives in OneLake as Delta tables and you want Import-like speed without a refresh pipeline — but design the model the way you would for Direct Lake specifically (simple RLS, no calculated columns, stable schema), not the way you'd design an Import model and hope it behaves the same.