Cost & Performance Optimization features in Microsoft Fabric - Microsoft Fabric Features That Delivers FinOps
Microsoft Fabric

Cost & Performance Optimization features in Microsoft Fabric - Microsoft Fabric Features That Delivers FinOps

Content type Blog Post
Author Francis Folaranmi
Publication Date 13 Jul, 2026
Reading Time 16 minutes

Introduction

Most FinOps conversations about Microsoft Fabric stop at the Capacity Metrics app and a pause schedule for dev environments. That’s the surface. Underneath it, Fabric has dozens of engine-level, storage-level, and architecture-level features that exist specifically to reduce how many Capacity Units (CUs) a given piece of work consumes. Some of these are switches you flip once. Others are habits, the kind of table maintenance routine a DBA would have run on SQL Server twenty years ago, just rebuilt for Delta Lake.

This is the deeper list, organized by where in the stack the saving happens: the Spark engine itself, the Delta tables sitting in OneLake, the architecture choices that prevent duplicate work, the way data moves into Fabric, the way queries get served back out, and the governance layer that watches all of it.

Part 1: Spark Engine and Compute Efficiency

1. High Concurrency Mode (shared Spark sessions)

Multiple notebooks, or multiple notebook activities inside one pipeline, can share a single Spark application instead of each spinning up its own session. Only the notebook that initiates the session is billed; everything that joins it afterward runs for free on the same session. The session-sharing limit has grown from 5 notebooks to 50, so an entire pipeline of bronze-to-gold notebooks can now run on one billed session instead of a dozen.

2. Native Execution Engine (NEE)

A vectorized, C++-based engine built on Apache Gluten and Velox that runs your existing Spark SQL and PySpark code faster with no code changes. Microsoft’s internal benchmarks showed roughly 4x faster performance on a 1TB TPC-DS workload, with some production jobs seeing up to 6x end-to-end gains. Faster execution on identical code means fewer CU-seconds for the same output. It is a one-checkbox setting at the environment level, though it currently falls back to standard Spark for JSON/XML formats, structured streaming, and ANSI SQL mode.

3. Intelligent Cache

Enabled by default on every Spark pool at a 50% cache size, this caches files read from OneLake or ADLS Gen2 (including via shortcuts) on local SSD at the node level. Repeated reads of the same file or table skip the remote storage call entirely. Microsoft cites up to 60% performance improvement on subsequent reads. It pays off most on workloads that re-read the same data repeatedly within a session; it offers little benefit on single-pass jobs or files larger than the cache itself.

4. Autoscale Billing for Spark

Routes Spark workloads to dedicated serverless compute, billed only for job runtime, completely separate from your main capacity’s CU pool. You set a maximum CU ceiling. Because Spark moves off the primary capacity, it no longer competes with Power BI refreshes or warehouse queries for the same pool, and it doesn’t trigger the bursting or smoothing behavior that can otherwise mask where cost is actually coming from.

5. Starter pool vs. custom pool billing mechanics

Both pool types bill only for active session runtime; you are never charged for cluster acquisition, Spark context initialization, or idle pool time. Sessions default to a 20-minute expiration, and a pool deallocates 2 minutes after that. The practical habit this creates: close sessions explicitly from the Monitoring hub instead of leaving notebooks open, since every extra minute of an active session is allocation you’re not using productively.

6. Bursting and smoothing

Standard capacities can burst up to 3x your purchased Spark VCores to absorb spikes, with CU consumption smoothed over a rolling window rather than billed as a hard instantaneous peak. A single job can be capped at the base core limit instead of the full burst allowance, which stops one batch job from monopolizing capacity and queueing out everyone else. For mixed workloads (ETL, ML, ad hoc BI on the same capacity), disabling job-level bursting is a concrete way to reduce contention without buying more capacity.

7. Job admission, concurrency limits, and queueing

By default, Fabric uses optimistic job admission, meaning a Spark job is admitted using its minimum core requirement and only scales up as capacity allows. Background jobs (pipeline-triggered, scheduled, Spark Job Definitions) queue when capacity is full rather than failing outright, with queue size tied to your CU limit and a 24-hour expiration. Interactive notebook jobs don’t queue; they’re rejected if the capacity is throttled. Understanding this distinction matters when deciding whether a job should run interactively or as a scheduled background activity.

Part 2: Delta Table and Storage Maintenance

This is the part of FinOps that looks the most like traditional database administration, and it’s also the part most teams skip until performance (and cost) visibly degrades.

8. OPTIMIZE (small file compaction)

Every write to a Delta table creates new Parquet files. Frequent small writes, especially from streaming or row-by-row ingestion, leave a table fragmented into thousands of tiny files. Reading many small files is slower and burns more CU-seconds than reading fewer large ones. OPTIMIZE consolidates them. It is a Spark SQL command, runnable from a notebook, a Spark Job Definition, or the Lakehouse Maintenance UI, but not from the SQL analytics endpoint or Warehouse editor.

9. V-Order

A write-time optimization applied as part of OPTIMIZE that sorts, encodes, and compresses Parquet files in a way the VertiPaq engine (used by Power BI Direct Lake) reads especially efficiently. Microsoft’s documented numbers: 40 to 60% faster cold-cache queries for Direct Lake, about 10% faster reads for the SQL analytics endpoint and Warehouse, and up to 50% better compression. The tradeoff is roughly 15% slower write times, which is why it’s usually applied selectively to gold-layer, Power BI-facing tables rather than every bronze table.

10. VACUUM (removing obsolete files and log history)

Deleting or updating rows in a Delta table doesn’t immediately free storage. The old files stick around as “tombstones” so Delta can support time travel and concurrent readers. VACUUM permanently removes files older than a retention threshold, the default is 7 days, reclaiming storage and keeping the transaction log from growing indefinitely. This is the closest thing in Fabric to the “shrink old log files” instinct that’s second nature in relational database administration. The Fabric portal blocks retention windows shorter than 7 days by default, since cutting that window too short can break time travel and concurrent operations; it requires explicitly overriding a Spark property to go lower.

11. Z-Order

A clustering technique applied during OPTIMIZE that co-locates related values (by date, customer ID, region, or whatever columns your queries filter on most) in the same files. This improves data skipping, meaning queries scan fewer files to answer the same filter. It’s most valuable on large, stable tables with predictable query patterns, and it’s typically run less frequently than plain OPTIMIZE, weekly or monthly rather than nightly.

12. Auto-compaction, optimize write, and Adaptive Target File Size

Rather than scheduling OPTIMIZE as a separate job after every load, auto-compaction and optimize write handle small-file prevention proactively at write time. Adaptive Target File Size is a documented Fabric feature that re-evaluates the ideal file-size target at the start of every OPTIMIZE run based on current table size and write patterns, removing the need for manual tuning. Microsoft’s own guidance states it can improve compaction performance by 30 to 60%. Pre-write compaction is generally cheaper than post-write compaction, so enabling it selectively on high-frequency, small-append tables (streaming ingestion in particular) is one of the more cost-effective table-level decisions available.

13. Fast Optimize

A refinement to the OPTIMIZE command itself: instead of blindly compacting every group of small files it finds, fast optimize evaluates whether merging a given group (“bin”) would actually reach a meaningful target size or file-count threshold first. Bins that wouldn’t benefit are skipped or only partially compacted. The practical effect is fewer unnecessary file rewrites over a table’s lifetime, which means OPTIMIZE itself becomes cheaper to run repeatedly, not just the data it produces.

14. Liquid Clustering

A newer alternative to static Hive-style partitioning and manual Z-Order maintenance. You declare which columns to cluster on and Fabric’s Spark runtime manages the physical layout automatically, improving file skipping for queries that filter on those columns. One important caveat worth flagging for anyone planning around it: in Fabric Runtime 1.3, liquid clustering uses a full rewrite strategy on every OPTIMIZE run for tables under 100GB, which can cause significant write amplification if combined with auto-compaction. Incremental liquid clustering, which avoids that full-rewrite cost, is only available starting in Fabric Runtime 2.0. Worth checking which runtime a workload is on before adopting this one.

15. Lakehouse Maintenance pipeline activity

OPTIMIZE and VACUUM don’t have to be manual, per-table clicks in the portal. The Lakehouse Maintenance activity in Data Factory pipelines runs both operations on a schedule, chained with Copy, Notebook, or Dataflow activities, with a DRY RUN option to preview which files are eligible for rewriting before committing compute to it. For an organization running multiple lakehouses across bronze, silver, and gold, this is what turns table maintenance from a thing someone occasionally remembers into an operational habit.

Part 3: Architecture Choices That Prevent Duplicate Work

16. Materialized Lake Views with optimal refresh

MLVs let you express a medallion transformation as a declarative SQL statement instead of a hand-built notebook. The FinOps mechanism is optimal refresh: Fabric inspects the Delta change feed and chooses the cheapest valid strategy automatically, skipping the refresh entirely if nothing changed, running incrementally if only new rows landed, or doing a full rebuild only when necessary. Enabling Change Data Feed on source tables is a prerequisite for incremental refresh; without it, Fabric can only choose between skip and full rebuild.

17. OneLake Shortcuts

Shortcuts are reference pointers, not data copies, to data in another workspace, another cloud, or an external source like ADLS, S3, or Dataverse. Every duplicated copy of data is duplicated storage cost and duplicated compute cost every time it gets reprocessed downstream. Shortcuts collapse that to one physical copy every Fabric engine reads natively. They also support caching for external sources (a configurable validity period), so repeat reads from, say, an S3 bucket hit local cache instead of round-tripping to the source every time.

18. Direct Lake mode

Power BI reads Delta tables in OneLake directly, with no Import-mode refresh cycle and none of the row-by-row cost of DirectQuery. There’s no separate copy of the data and no scheduled refresh job consuming CUs on a timer. For large fact tables where Import refreshes used to be a major recurring CU line item, this is consistently one of the highest-leverage single changes available, especially when the underlying table is also V-Ordered.

19. Mirroring

Continuously replicates data from supported sources (Azure SQL Database, Cosmos DB, Snowflake, and a growing list including SQL Server, PostgreSQL, BigQuery, and Oracle in preview) directly into OneLake as Delta tables, without you building or maintaining a single ingestion pipeline. Mirroring storage is included free up to a limit tied to your capacity SKU (for example, F64 includes a substantial free mirroring allowance), and it removes the watermark and merge logic that a hand-built incremental pipeline would otherwise require, which is itself an indirect compute saving.

Part 4: Data Ingestion and Movement

20. Fast Copy in Dataflow Gen2

Switches large ingestion to a copy-optimized backend, the same one used by pipeline Copy activities, instead of the Mashup engine. Microsoft’s own benchmark on a 6GB ingestion job showed an 8x improvement in speed and a 3x reduction in cost. It works best for ingestion-time loads with light transformations (column selection, renaming, type changes); for heavier transformation, the recommended pattern is Fast Copy to land data in staging, then a follow-on query for the transform.

21. Copy Job incremental mode

Copy Job is Fabric’s newer low-code data movement experience, and its incremental mode handles watermark logic automatically. It costs more per operation than a full copy (roughly 3 CU versus 1.5 CU), but because it only moves changed rows instead of the entire dataset, it processes far less data overall on every run after the first. For simple recurring loads, it also tends to carry less orchestration overhead than a custom pipeline built from Lookup, Copy, and Stored Procedure activities.

22. Dataflow Gen2 staging, the Modern Evaluator, and partitioned compute

Staging materializes an intermediate result once so downstream queries reference it instead of re-hitting the source repeatedly, which matters when multiple derived queries draw from the same load. The Modern Query Evaluation Engine, enabled by default on new CI/CD Dataflow Gen2 items, reduces evaluation overhead in the underlying Power Query engine. Partitioned compute (in preview) parallelizes transformation work further. None of these eliminate Dataflow Gen2’s inherent cost relative to Pipelines for simple ingestion, query folding and minimizing unnecessary columns and rows early in a query remain the biggest levers there, but together they reduce the cost of the transformation-heavy work Dataflow Gen2 is actually built for.

Part 5: Query Serving and Refresh Efficiency

23. Result Set Caching

Persists the final result set of qualifying SELECT queries in Fabric Data Warehouse and the Lakehouse SQL analytics endpoint, so an identical subsequent query returns from cache instead of recompiling and rescanning. It applies to pure SELECT queries against tables of at least 100,000 rows, and it’s invalidated automatically if the underlying table changes. Worth checking the current status before relying on it in a given workspace; it has had periods of being disabled while Microsoft addresses known issues, and you can confirm caching behavior directly by checking the data_scanned_remote_storage_mb column in queryinsights.exec_requests_history, a zero value means the query was fully served from cache.

24. Incremental statistics refresh

Warehouse and SQL analytics endpoint statistics used to require a full recompute to stay accurate. Incremental statistics refresh updates only the portion of a column’s statistics affected by new inserts or appends, which speeds up the refresh itself and indirectly speeds up every query that depends on accurate statistics for its execution plan.

25. Table and partition-level semantic model refresh

The default behavior for a scheduled Power BI semantic model refresh is to refresh the entire model. The Semantic Model Refresh activity in Data Factory pipelines lets you target specific tables and partitions instead, so a daily refresh of a fact table doesn’t also recompute slowly changing dimension tables that haven’t moved. Combined with incremental refresh policies on large models, this is one of the more direct ways to cut recurring Power BI refresh cost without touching the underlying data architecture at all.

Part 6: Governance and Capacity Management

26. The Fabric Capacity Metrics app

The instrument panel for everything above. It shows real-time and historical CU consumption against your purchased SKU, exactly when and how throttling occurred, overage carryforward and burndown, OneLake storage by workspace, and an item-level breakdown of which semantic models, notebooks, or pipelines are the heaviest consumers. A monthly review of this app, owned by a named person, is the habit that separates organizations whose Fabric bill stays predictable from those who get surprised by it.

27. Surge protection and capacity overage protection

Caps background activity (refreshes, AI jobs) so it can’t starve interactive, user-facing reports during busy periods, using configurable rejection and recovery thresholds. Newer overage protection capabilities, in preview, guard further against runaway cost from unexpected spikes. The important caveat: this is a safety net that defers or rejects background work, not a substitute for sizing capacity correctly, since deferred jobs may need to be rerun.

28. Pause and resume on capacity

For non-production capacities, the most direct lever available. Pausing stops all compute-driven CU consumption entirely. OneLake storage continues billing at its pay-as-you-go rate even while paused, since pausing stops compute, not storage, and data consumed via shortcuts from a paused capacity is billed against the consuming capacity rather than the paused one, so downstream consumers elsewhere aren’t disrupted. Automating pause schedules outside business hours for dev and test environments is consistently cited as a fast, low-risk win.

29. Reserved capacity and the F64 licensing threshold

Microsoft’s published figure for a one-year Fabric capacity reservation is savings of up to 40.5% compared to pay-as-you-go pricing (Power BI Premium P-SKUs excluded). This is a genuine commitment discount applied automatically on an hourly basis to matching usage, not a marketing estimate. Separately, and confirmed directly in Microsoft’s Fabric licensing documentation, capacities at F64 or above let users with only a free Power BI license view content without needing an individual Pro license, which for organizations with a broad reporting audience can represent a bigger saving than the compute optimization itself. The sequencing that works best: validate actual usage on pay-as-you-go or autoscale first, then convert to a reservation once the baseline is understood, since the reservation discount doesn’t carry over to hours where you didn’t have workloads consuming CUs.


Bringing It Together

Group these twenty-nine by what they actually do and a pattern shows up. High concurrency mode, the Native Execution Engine, intelligent cache, and autoscale billing reduce what a job costs while it runs. OPTIMIZE, V-Order, VACUUM, Z-Order, fast optimize, liquid clustering, and auto-compaction keep the underlying tables from degrading into a state where every query costs more than it should. Materialized Lake Views, shortcuts, Direct Lake, and Mirroring reduce how much duplicate work and duplicate data exist in the first place. Fast Copy, Copy Job, and Dataflow Gen2’s newer engines reduce the cost of getting data in. Result set caching, incremental statistics, and partition-level refresh reduce the cost of serving it back out. Capacity Metrics, surge protection, pause and resume, and reserved capacity sit on top as the governance layer that catches whatever the architecture didn’t already prevent.

The teams that get this right don’t treat it as a one-time cleanup. They treat VACUUM and OPTIMIZE the way a DBA treats index maintenance: regular, scheduled, unglamorous, and measurable, that discipline is most of the job.

About the author

Sam Debruyn

Freelance Data Platform Architect & Senior Data Engineer | Fabric / Azure / dbt | recognized as Microsoft Data Platform MVP and dbt Champion | meetup organizer & public speaker

S, Debruyn (09/07/2026) Introducing the Fabric Data Warehouse CLI and MCP Server. AIntroducing the Fabric Data Warehouse CLI and MCP Server — Sam Debruyn