Microsoft Fabric Runtime 2.0 Internals
Comprehensive architectural breakdown of Microsoft Fabric Runtime 2.0 (Apache Spark 4.1, Delta Lake 4.2, Python 3.13, Java 21, Scala 2.13, Azure Linux 3.0). Covers the ANSI standard execution shift, the critical ANSI × Gluten SIMD offload trade-off, Spark Connect, Python UDAFs, and production migration runbooks.
1. Chronological Timeline of Fabric Runtimes
Understanding the component evolution across Fabric runtimes is essential when upgrading existing Lakehouse pipelines or debugging subtle behavioral discrepancies.
| Runtime Version | Spark Engine | Delta Lake | Python & Java | OS & Kernel | Key Architectural Milestones |
|---|---|---|---|---|---|
| Runtime 1.1 | Spark 3.3.4 | Delta 2.2.0 | Python 3.10 Java 11 |
Mariner 2.0 |
Synapse legacy keys (spark.synapse.*), initial Fabric release baseline.
|
| Runtime 1.2 | Spark 3.4.1 | Delta 2.4.0 | Python 3.10 Java 11 |
Azure Linux 2.0 | First iteration of Native Execution Engine (Gluten/Velox preview); legacy optimize write keys. |
| Runtime 1.3 (LTS) | Spark 3.5.2 | Delta 3.2.1 | Python 3.11 Java 11 |
Azure Linux 2.0 |
spark.microsoft.delta.optimizeWrite.enabled standard; ANSI off by
default; Liquid Clustering preview; Deletion Vectors supported.
|
| Runtime 2.0 (GA) | Spark 4.1.0 | Delta 4.2.0 |
Python 3.13 Java 21 (LTS) |
Azure Linux 3.0 | ANSI default ON; Liquid Clustering GA; Spark Connect gRPC; Python UDAFs; Generational ZGC; Velox SIMD AVX-512 acceleration. |
2. Architectural Blueprint: Runtime 1.3 to 2.0 Changes
3. The ANSI × Native Execution Engine (NEE) Conflict
The single most impactful behavioral difference in Fabric Runtime 2.0 is the interaction between ANSI SQL mode and the Native Execution Engine (Gluten/Velox).
spark.sql.ansi.enabled=false). In Spark 4.1 (Runtime 2.0), ANSI mode
is enabled by default. Under ANSI mode, integer overflows and invalid
string-to-numeric casts throw runtime exceptions instead of returning NULL.
Because Velox SIMD C++ kernels implement non-ANSI silent NULL semantics for certain
operations, Gluten planner
intercepts ANSI expressions and forces a fallback to JVM Janino bytecode
(VeloxColumnarToRowExec), resulting in a 2x to 4x execution slowdown.
How to Mitigate the ANSI vs NEE Conflict
# Strategy 1: Use try_cast() in SQL - Preserves native SIMD acceleration under ANSI mode
df_optimized = spark.sql("""
SELECT
order_id,
try_cast(amount_raw AS DOUBLE) AS amount,
try_cast(tax_raw AS DOUBLE) AS tax
FROM bronze_orders
""")
# Strategy 2: For pure batch ETL pipelines where performance supersedes ANSI strictness
spark.conf.set("spark.sql.ansi.enabled", "false")
4. Interactive Migration Diagnostic Simulator
Select a code pattern to inspect the behavioral transition from Runtime 1.3 to Runtime 2.0:
CAST('abc' AS INT)
CLUSTER BY (cust_id)
@udaf(returnType=...)
SparkConnectClient
[Runtime 2.0 (Default)]: Throws
SparkNumberFormatException; triggers JVM fallback.[Remediation]: Replace with
try_cast('abc' AS INT) to retain native Velox execution without error.
5. V-Order (spark.sql.parquet.vorder.default) — Workload Decision Matrix
Enabling V-Order globally across all workloads is a major anti-pattern in Microsoft Fabric. V-Order imposes a 10% to 15% write-time CPU & memory overhead during writes in exchange for ~20% to 40% faster read scans in Power BI Direct Lake and the Polaris SQL Endpoint.
| Workload / Architecture Layer | Recommended V-Order Setting | Technical Rationale & Capacity Impact |
|---|---|---|
| Bronze / Raw Ingestion | spark.sql.parquet.vorder.default = false |
Maximize Write Throughput: Raw data is never queried directly by Power BI. Paying 15% write CPU overhead burns capacity CUs with zero downstream benefit. |
| Streaming Micro-Batches | spark.sql.parquet.vorder.default = false |
Minimize Ingestion Latency: Frequent micro-batches (5–30s triggers) suffer severe latency inflation if calculating dictionary sort orders on every batch commit. |
| Intermediate ETL & Scratch Staging | spark.sql.parquet.vorder.default = false |
Transient Data: Temporary staging tables that are dropped or rewritten should never pay the V-Order encoding cost. |
| Silver Transformed Layer |
spark.sql.parquet.vorder.default = false(Unless queried by Direct Lake) |
Batch Processing: Spark queries scan columnar Parquet with native predicate pushdown and do not require V-Order dictionary layouts unless serving BI directly. |
| Gold Reporting & Semantic Marts | spark.sql.parquet.vorder.default = true |
Sub-Second BI Acceleration: Essential for Power BI Direct Lake VertiPaq memory paging and high-concurrency SQL analytics endpoints. |
| Scheduled Off-Peak Maintenance | Run OPTIMIZE gold_table |
Decoupled Maintenance: Delta OPTIMIZE automatically applies
V-Order during off-peak compaction without impacting production ingestion SLAs.
|
# Bronze / Streaming Pipeline: Disable V-Order to minimize write latency and save CUs
spark.conf.set("spark.sql.parquet.vorder.default", "false")
# Gold Aggregation Pipeline: Enable V-Order for Direct Lake sub-second dashboard queries
spark.conf.set("spark.sql.parquet.vorder.default", "true")
6. Fact-Checked Configuration Reference: When is %%configure Actually Needed?
In Microsoft Fabric, %%configure -f forces a complete kernel restart and
allocates a new session. It should only be used when configuring session-locked
infrastructure properties:
| Configuration Setting | Proper Scope | Why It Belongs Here |
|---|---|---|
spark.sql.adaptive.* (AQE targets) |
Runtime Scope (spark.conf.set) |
Dynamic execution rules evaluated per query. Never restart session for AQE. |
spark.sql.parquet.vorder.default |
Runtime Scope (spark.conf.set) |
Toggled per ETL pipeline (disable on Bronze, enable on Gold). |
delta.enableDeletionVectors |
Table DDL (TBLPROPERTIES) |
Delta metadata property; invalid inside Spark session conf. |
| Custom PyPI Index / Extra Packages | Session-Start (%%configure) |
Requires pip resolution before SparkSession initialization. |
| Custom Pool Executor Core/Memory Sizing | Session-Start (%%configure) |
Allocates physical JVM executor container shapes on custom pools. |
7. Validated Workload Defaults & Configuration Scopes
Important Validation Finding: AQE settings such as
spark.sql.adaptive.advisoryPartitionSizeInBytes and
parallelismFirst are runtime-mutable SQL configurations. Putting them in
%%configure -f is an anti-pattern that forces an unnecessary session restart.
In Microsoft Fabric, Starter Pools require ZERO %%configure boilerplate.
All tuning should happen dynamically per-cell via spark.conf.set() or at table
creation via TBLPROPERTIES.
Archetype 1: Bronze & High-Frequency Streaming Ingestion (< 50 GB)
Optimized for raw ingestion speed. Skips V-Order write overhead; uses minimal shuffle sizing.
# Bronze / Ingestion: Maximize write throughput (Skip V-Order, tune small shuffle)
spark.conf.set("spark.sql.parquet.vorder.default", "false")
spark.conf.set("spark.sql.shuffle.partitions", "128")
-- Standard Delta Table (Optimized Write is active by default in Fabric)
CREATE TABLE bronze_telemetry (
device_id BIGINT,
timestamp TIMESTAMP,
payload STRING
) USING DELTA;
Archetype 2: Silver CDC & Heavy Merge ETL (100 GB – 1 TB)
Optimized for row mutations and incremental change tracking. Uses 128 MB write bins with Deletion Vectors.
# Silver Merge / CDC: 128 MB bins minimize rewrite footprint during MERGE
spark.conf.set("spark.microsoft.delta.optimizeWrite.binSize", "134217728")
spark.conf.set("spark.sql.parquet.vorder.default", "false")
spark.conf.set("spark.sql.adaptive.skewJoin.skewedPartitionFactor", "5")
ALTER TABLE silver_orders SET TBLPROPERTIES (
'delta.enableDeletionVectors' = 'true',
'delta.enableChangeDataFeed' = 'true'
);
Archetype 3: Gold Layer & Direct Lake BI Serving (Consumption)
Optimized for Power BI Direct Lake VertiPaq memory paging. Uses V-Order and 512 MB file bin targets.
# Gold Consumption: Enable V-Order for Direct Lake sub-second queries
spark.conf.set("spark.sql.parquet.vorder.default", "true")
spark.conf.set("spark.microsoft.delta.optimizeWrite.binSize", "536870912") # 512 MB bins for Direct Lake
CREATE TABLE gold_sales_mart (
sale_id BIGINT,
customer_id INT,
store_id INT,
total_amount DOUBLE
) USING DELTA
CLUSTER BY (customer_id, store_id)
TBLPROPERTIES ('delta.enableDeletionVectors' = 'true');
-- Scheduled Maintenance
OPTIMIZE gold_sales_mart;
Archetype 4: Heavy ML Prep & Wide Shuffle (> 1 TB, Cache-Heavy)
Optimized for massive distributed joins and wide shuffles. Scaled dynamically per notebook execution.
# Large-Scale Shuffle (> 1 TB): Scale shuffle partitions and broadcast thresholds dynamically
spark.conf.set("spark.sql.shuffle.partitions", "8192")
spark.conf.set("spark.sql.autoBroadcastJoinThreshold", "268435456") # 256 MB broadcast ceiling
spark.conf.set("spark.sql.adaptive.advisoryPartitionSizeInBytes", "134217728")