DirectLake vs Import vs DirectQuery
Power BI has three ways to query data. Choosing the right one affects performance, freshness, model size, and capacity cost. In Fabric, DirectLake is the default — but you should understand all three to diagnose issues.
Comparison
| Factor | DirectLake | Import | DirectQuery |
|---|---|---|---|
| Data copy? | No — reads from OneLake | Yes — copies into model memory | No — queries source live |
| Query speed | Fast (VertiPaq on Delta) | Fastest (in-memory VertiPaq) | Slowest (live SQL per interaction) |
| Data freshness | After Lakehouse refresh | After model refresh | Real-time |
| Model size limit | Per capacity tier (3–100 GB) | Per capacity tier | No limit (but CU cost per query) |
| CU cost | Low (cached reads) | Medium (refresh + query) | High (every click = SQL query) |
| Supported source | Lakehouse only | Any | Warehouse, SQL, external |
| DAX compatibility | Most DAX works | Full DAX | Some DAX limited by source SQL |
DirectLake (Default for Fabric)
DirectLake reads Delta/Parquet files directly from OneLake using the VertiPaq engine — the same in-memory columnar engine that powers Import mode. But instead of copying data into the model, it memory-maps the files from OneLake.
Result: Import-speed queries with DirectQuery-level freshness.
When DirectLake Falls Back
DirectLake can't handle every query. When it encounters something it can't optimize, it silently falls back to DirectQuery — which is much slower and consumes more CUs.
Common fallback triggers:
- Model exceeds the capacity tier's DirectLake size limit
- Query uses unsupported DAX (certain iterators on large tables)
- Calculated columns reference other tables
- Too many columns loaded (DirectLake loads all columns in referenced tables)
How to Detect Fallback
- Open the report in the Fabric service
- Open Performance Analyzer (View → Performance Analyzer)
- Click Start recording → interact with a slow visual
- In the trace, look for the query type:
DirectLake= goodDirectQuery= fallback occurred
- If you see DirectQuery, optimize the DAX or reduce model scope
Import Mode (Legacy)
Import copies all data into the semantic model's in-memory cache. Queries are fast because everything is in RAM. But:
- Data is stale between refreshes (typically scheduled 1–8x per day)
- The model duplicates storage (data in Lakehouse + data in model cache)
- Refreshes consume CUs (the import process itself is compute-intensive)
In Fabric, prefer DirectLake over Import. DirectLake gives you the same query speed without the data duplication or refresh overhead.
DirectQuery (Use with Warehouse Only)
DirectQuery sends a SQL query to the source for every user interaction — every slicer click, every page load, every filter change. No data is cached.
When to use it:
- Your data is in a Fabric Data Warehouse (which doesn't support DirectLake)
- You need real-time data (can't wait for even a 15-minute Lakehouse refresh)
- The source is an external SQL database accessed via gateway
When to avoid it:
- High concurrent users (each user generates live SQL queries → CU spike)
- Complex DAX that doesn't translate well to SQL
- When DirectLake is an option (always prefer DirectLake)
Decision Tree
Is the data in a Fabric Lakehouse?
├── Yes → Use DirectLake
└── No
├── Is it in a Fabric Data Warehouse? → Use DirectQuery
├── Is it in an external SQL database? → Use DirectQuery (via gateway)
└── Is it a file/API? → Load into Lakehouse first → Use DirectLake
Related Documentation
Query folding, DAX optimization, visual reduction
Lakehouse vs Warehouse vs SQL DB