Fabric Emulator

v0.33.0latest release · docs built from latest-eec3e8c →

Run your Fabric work on a laptop. Then prove it behaves.

A local Microsoft Fabric: the control plane, OneLake, and engines that genuinely run your code. Workspaces, items and their CI/CD definitions, workspace RBAC, git integration, jobs and the 202/poll long-running-operation contract, validating Microsoft Entra bearer tokens against entra-emulator exactly as real Fabric validates against Entra.

Microsoft's own tools drive it: fabric-cicd, the Fabric CLI, dbt-fabric, the Terraform provider, the VS Code extension. The same pipeline runs unmodified here and against a real tenant.

Every supported capability names the test that witnesses it, and CI fails when one loses its witness. Where something is a contract and not an engine, this page says which.

138capabilities graded real, of 158
599witnesses over 125 claims
45CI jobs driving real clients
62end-to-end suites
56pages of documentation

The gap this is built around

Testing Fabric work against Fabric means a tenant, a capacity and a cloud round trip for every iteration. The consequences are specific, and they are not really about speed.

A pull request cannot have a capacity

A capacity is shared and always on. Nothing spins one up per branch, so the Fabric part of a change is the part continuous integration never exercises.

Here: `docker compose up`, per run, on the runner

A workspace is shared state

One run's cleanup is another run's broken fixture. Teams either serialise on a workspace or discover the collision as a failure in somebody else's job.

Here: a tenant per test, created and thrown away

So the risky parts go untested

The deployment pipeline, the OneLake writes, the notebook that only fails on real data. They break in production because production was the first place they ran.

Here: the same code, offline, before it is pushed
An emulator cannot assert that it behaves like Fabric.

That is the whole difficulty, and it is why this project spends more effort on evidence than on features. Real clients drive the surfaces, the differences that remain are written down rather than left to be discovered, and the same suite can be pointed at a real tenant with FABRIC_TARGET to find out where the two disagree.

How it fits together

One Go binary is the control plane and OneLake. The engines beside it are real, unmodified software: Sail for Spark, SQL Server for T-SQL, Microsoft's own Kusto container for KQL, Apache Kafka for Eventstream. No client knows it is not Fabric.

Microsoft's toolsfabric-cicd · fab CLIdbt · TerraformVS Code · azcopyyour own pipelineentra-emulatorreal signed JWTsfabric-emulatorcontrol plane · RBACOneLake (ADLS · Blob)Livy · TDS · pipelinesLRO engine · MCPOneLake on diskreal Delta bytesshortcutsitem-scoped securitySail (Spark Connect, Rust)notebooks · Livy · Delta writeSQL Serverwarehouse T-SQL over real TDSKusto (Microsoft's container)KQL eventhouses · profileApache Kafka (KRaft)Eventstream · profile
Tokens are validated, not trusted. Bytes are written, not recorded. The binary implements Fabric's wire protocol; the compute beside it is somebody else's engine, unmodified.

What it runs

138 of 158 graded capabilities do real work.9 are a faithful contract without an engine, 3 need an engine that is not the default, and 8 are an honest 501. Each row below links to the page that carries the detail.

Control plane real

Workspaces, items and their CI/CD definitions, folders, workspace RBAC enforced from the validated bearer principal, git integration, deployment pipelines, jobs, and the 202/poll long-running-operation contract. Fabric Core MCP included.

07 — control-plane API

OneLake real bytes

Both dialects of the data plane, ADLS Gen2 and Blob, addressed as Fabric addresses them. Real Delta on disk with put-if-absent commit atomicity, shortcuts, and item-scoped OneLake security with RLS and CLS.

08 — OneLake ·54 — OneLake security

Notebooks and Spark real engine

Sail, a Rust Spark Connect implementation, is the default: sessions start in milliseconds and Delta is native. The JVM Spark overlay is available as an oracle when a surface needs a real JVM, and the two are measured against the same probes.

20 — the engine ·engine matrix

Warehouse and T-SQL real TDS

A real TDS endpoint backed by SQL Server, so Microsoft's own drivers connect. Row-level security, column-level security and dynamic data masking are enforced by the database rather than filtered on the way out.

16 — warehouse ·29 — T-SQL parity

Pipelines and orchestration real interpreter

Data Factory pipelines with the expression language and control flow interpreted for real, activities dispatched to the engines above, and Apache Airflow jobs.

23 — deployment pipelines

Real-Time Intelligence profile

KQL runs on Microsoft's own Kusto container and Eventstream on Apache Kafka, both behind an opt-in profile because most tests never reach them and the images are not small.

25 — RTI ·51 — Eventstream

The same code against real Fabric by configuration

One environment variable points the conformance suite at a real tenant instead of this one. That is the fidelity oracle: divergences found there become parity-map rows rather than surprises.

21 — real Fabric toggle

Governance and catalog profile

OpenMetadata catalogues the emulated estate — workspaces, lakehouses, Delta tables — so lineage and glossary work has something to run against locally.

22 — OpenMetadata

How the claims are checked

Parity here is not self-assessed. 599 witnesses are mapped to125 claims, and a claim whose witness is renamed or deleted fails the build rather than quietly becoming an assertion.

KindWhat it isWhy it ranks where it does
ci:A CI job in which a real third-party client does the talkingStrongest. A packaged release of somebody else's software, over a network, with no knowledge of this codebase
sdk:A Go test in which Microsoft's own client speaks the protocolThird-party evidence too, but in-process rather than a released client over a network, so it ranks below ci:
go:A Go test: real HTTP, real signed JWTs, real RBACOur own client. Proves the code agrees with itself, which is the weakest thing a green test can mean
boundary:The claim is scoped by a documented limitationNot a witness at all, and named as such, with the reason recorded beside it
A witness whose name exists is not a witness that ran.

That gap cost real time twice here, so the checker detects skipped tests and gated jobs rather than taking a name on trust. The parity map is the ledger, its history shows how every row moved release by release, and ecosystem conformance lists the real clients driving it in CI.

Honest status

The full ledger is the parity map. These are the entries most likely to matter before you start, stated here rather than found later.

CapabilityStatusWhat that means
Java and Scala UDFs, spark.jarsnot on the default engineSail has no JVM classloader, so a JAR is accepted and inert. The JVM overlay has a real one
sc, the RDD API, spark._jvmpartly, by measurementSpark Connect exposes no SparkContext or JVM bridge; the measured subset that does work is in the engine matrix rather than asserted
Structured streamingpartlyreadStream plans, and durable sinks pull a micro-batch on the Livy path
Dataflow Gen2management onlyThe item and its definition round-trip; refresh and in-pipeline execution fail by name, because the Power Query M engine is not something to fake
Purview scanning and system classifiersnot implementedA scan is an engine, and the ~200 built-in classifiers are proprietary detection patterns. This row can never move
On-prem gateways and connectorsnot implementedAbsent rather than stubbed
Real-tenant conformancegated, unwitnessedThe suite and the workflow exist; the secrets that would point them at a real tenant are unset, so that leg has never run — and a skipped run is not evidence
Local development tool only.

Intentionally insecure: no real authorization boundary, self-signed TLS, seeded credentials. Run it on localhost only.

Get it

A single Go binary, or the container image. Homebrew and GHCR publish on every tag; winget lags, because Microsoft's moderation takes days.

brew install calvinchengx/tap/fabric-emulator
winget install calvinchengx.fabric-emulator
go install github.com/calvinchengx/fabric-emulator/cmd/fabric-emulator@latest
docker pull ghcr.io/calvinchengx/fabric-emulator:latest

Every option, including the archives and the compose files, is in installation. What each running mode costs in memory and startup time is in running modes.

Run the whole family

One command brings up the control plane, OneLake, Entra, Key Vault and the compute sidecars, with Spark-compatible compute already attached. Check the machine first; make doctor names what is missing rather than letting it surface later as a broken recipe.

git clone https://github.com/calvinchengx/fabric-emulator
cd fabric-emulator
make doctor
docker compose up          # or: make up, which adds OpenMetadata and Airflow

Then mint a token, create a workspace and write to OneLake, in the quickstart — or take the medallion tutorial from bronze through gold. Allow the runtime 8 GB; the six default services idle at about 530 MB.