Articles

The API layer that wasn’t supposed to matter

The API layer that wasn't supposed to matter

The strangest platform announcements are usually the boring ones.

Nobody throws a party for source control. Nobody leans back and says, “Hell yes, deployment pipelines,” with a straight face. The applause goes to the flashy stuff: faster engines, new runtimes, clever demos. Then a quiet release slips past and changes the quality of production systems more than all the fireworks did.

That is what just happened with the general availability of source control and CI/CD support for the API for GraphQL in Microsoft Fabric.

On the surface, this looks minor. GraphQL artifacts can now live in Git. Teams can review changes through pull requests. APIs can move through Fabric deployment pipelines. It reads like housekeeping.

It is also the line between an API you demo and an API you trust.

The boring part is the point

GraphQL is easy to misread here. The real story is not query syntax. It is operational discipline.

Before this release, you could build an API for GraphQL on top of Fabric data sources. What you could not do cleanly was treat that API like the rest of your engineering system. It lived in an awkward middle state: important enough to matter, but not governed with the same rigor as the notebooks, jobs, and other artifacts around it.

Now Fabric supports Git integration for GraphQL items and supports GraphQL items in deployment pipelines. That means teams can version API changes, review them, and promote them across environments using the same lifecycle machinery they already use elsewhere in Fabric.

If you have ever cleaned up a production issue, you know why this matters. Production problems do not always come from spectacular failures. Quite often they come from a configuration that drifted, a schema that changed without review, or an environment that no longer matches the one everybody tested. The system is not obviously broken. It is slightly different in exactly the wrong place.

This release goes straight at that kind of failure.

What became generally available

The official blog post is short, which is fine because the details are the useful part.

Fabric now supports three things for API for GraphQL that matter in real engineering work.

First, you can version GraphQL artifacts in Git. Microsoft says GraphQL items can be synchronized with a repository so teams can track changes, collaborate, and roll back when needed. The docs also describe these items as Infrastructure as Code stored in the connected repository.

Second, you can put those GraphQL items through deployment pipelines. Fabric stages such as Development, Test, and Production can now carry GraphQL APIs forward just like other supported items.

Third, the workflow is reviewable. Microsoft explicitly calls out pull requests, branching, and governance around API changes. That sounds procedural until you remember what an API actually is: a contract. If the contract changes, review is not bureaucracy. It is the work.

One line in the docs deserves more attention than it will probably get: during deployment, only metadata is copied. The API metadata moves. The actual data does not. That sentence tells you how to think about promotion. You are not moving datasets through environments. You are moving the API definition that points at them.

The choice that changes deployment behavior

Here is the part most teams will miss the first time through.

The deployment story changes sharply depending on which authentication method you chose when you created the API.

Fabric supports two connectivity options for API for GraphQL: Single sign-on (SSO) and Saved credentials. They are not interchangeable, and the difference is not cosmetic.

If you use SSO, the docs say API clients use their own credentials to access the data source. Microsoft positions this option for Fabric data sources such as lakehouses, warehouses, and SQL analytics endpoints. More important for CI/CD, the docs say that when you deploy an SSO-based API from one workspace to another, the API in the target workspace automatically binds to the local copy of the data source in that target workspace, assuming both the API and the data source were deployed from the same source workspace.

That is a big deal. Dev can point to dev. Test can point to test. Production can point to production. The platform handles the rebinding.

If you use Saved credentials, the story changes. Microsoft says this mode is for cases where a shared credential sits between the API and the data source, including Azure data sources such as Azure SQL Database. In deployment pipelines, the docs say autobinding does not happen. The deployed API in the target workspace stays connected to the data source in the source workspace. Microsoft is blunt about the consequence: you must manually reconfigure connections or create new saved credentials in each target environment.

Same deployment pipeline. Opposite behavior. That is not a side note. That is the fact that will decide whether your rollout feels clean or haunted.

The docs add one more constraint that is easy to miss: once you choose an authentication method for an API, that choice applies to all data sources in that API. You cannot mix SSO and Saved credentials inside the same API.

The trap is not GraphQL. It is drift.

This is why Spark teams should care, even if they do not think of themselves as GraphQL teams.

A Spark team can do everything right in the data layer and still ship a messy consumer experience if the API layer is managed by hand. The notebook change gets reviewed. The lakehouse change gets tested. Then the API definition sits off to the side, touched manually, promoted inconsistently, and remembered by one person who is suddenly unavailable when something breaks.

Git integration and deployment pipelines do not make that risk vanish, but they drag it into the light. The API becomes reviewable. The history becomes visible. Rollback becomes possible.

And Fabric’s docs are refreshingly plain about where the remaining traps still are.

If your source API connects to a data source in a different workspace, the deployed API stays connected to that external source regardless of authentication method. Autobinding only works when the API and the data source start in the same source workspace.

There is also a schema caveat with real operational bite: GraphQL APIs in Fabric do not automatically detect schema changes in their underlying data sources. If a table or view changes, the API keeps using the schema it captured earlier until you refresh the API metadata yourself. Microsoft says that may mean updating the schema inside the API item, removing and re-adding columns, or in some cases removing and reattaching the whole data source.

That is not pretty. It is, however, the kind of detail serious teams need before they learn it the hard way.

What smart teams will do next

The practical response to this release is not excitement. It is inventory.

Start with a simple question: which of our GraphQL APIs use SSO, and which use Saved credentials?

That question now tells you something important about deployment behavior. If the API uses SSO and the data source lives in the same source workspace, pipeline promotion can autobind to the local target copy. If the API uses Saved credentials, you need an explicit post-deployment step to reconfigure the connection in each environment. If the API points across workspaces, do not expect autobinding to rescue you.

Then do the obvious thing teams postpone: connect the workspace to Git, commit the GraphQL artifacts, and review the resulting definitions like they matter. They do matter. An API is not decoration around the data platform. It is the part other systems actually touch.

After that, run a deployment pipeline on purpose, not during an outage. Promote an API from Development to Test. Confirm what bound where. Check whether the target API is using the data source you think it is using. If you depend on Saved credentials, write the reconfiguration step into the runbook now, while everyone is still calm.

Finally, treat schema refresh as a real operational task. If upstream tables or views change, do not assume the GraphQL layer will quietly keep up. The docs say it will not.

Why this matters more than it looks

People love dramatic turning points. Most production reliability does not arrive that way.

It arrives through small controls that remove whole categories of avoidable mistakes. Source control does that. Pull request review does that. Deployment pipelines do that. Clear rules about autobinding do that too, especially when the rules are strict enough to kill wishful thinking.

That is why this release matters.

Not because GraphQL suddenly became more fashionable. Not because CI/CD sounds good in a slide deck. It matters because Fabric just closed one of the classic weak spots in a data platform: the gap between building an access layer and governing it like production software.

For Spark teams, that is the real headline. The data job is not finished when the table is correct. It is finished when the contract that exposes that table can move through environments without guesswork.

That is what generally became available here. Not a shiny new abstraction. Something rarer.

A way to be less surprised later.

Read the docs, not just the headline

If you want the primary sources, start here:

This post was written with help from anthropic/claude-opus-4-6

DeltaFlow just changed the CDC conversation for Fabric Spark teams

DeltaFlow just changed the CDC conversation for Fabric Spark teams

A row changes in your operational database. That should be useful in seconds. Too often it turns into a side quest.

Raw CDC feeds are ugly. Debezium envelopes. Nested payloads. Schema drift. Then Spark teams spend their time turning change events back into tables. It is expensive work, and most of it is drudgery.

DeltaFlow is Fabric’s shot at removing that drudgery.

Microsoft’s docs and March 2026 blog posts describe DeltaFlow as a preview capability in Fabric Eventstreams. It takes raw Debezium CDC events and reshapes them into analytics-ready streams that mirror the source table structure. The stream keeps the source columns and adds metadata like change type and timestamps. Eventstreams handles schema registration, destination table management, and schema evolution. You turn it on by choosing “Analytics-ready events & auto-updated schema” during connector setup.

That is the part Spark teams should care about. Less time parsing CDC envelopes. More time writing logic that matters.

What is actually supported

Do not assume every CDC connector gets this.

The Eventstreams overview and connector docs tie DeltaFlow preview to four sources:
– Azure SQL Database CDC
– Azure SQL Managed Instance CDC
– SQL Server on VM DB CDC
– PostgreSQL Database CDC

The same overview lists MySQL Database CDC, MongoDB CDC, and Azure Cosmos DB CDC as Eventstreams connectors too. They are connectors. They are not called out with DeltaFlow preview support. If your estate runs on those systems, the old cleanup work does not disappear.

Why this changes the Spark path

Eventstreams now also has a Spark Notebook destination in preview. The destination can route Eventstream data directly into a Spark notebook and start a Spark Structured Streaming job.

That shortens the path.

Instead of dragging raw CDC into Spark and cleaning it up there, you can test a pipeline where Eventstreams does the CDC shaping first and Spark starts with data that already looks like tables. The payback is simple. Spark can spend its budget on joins, enrichment, aggregations, and writes instead of JSON surgery.

There is a second benefit. Microsoft says the DeltaFlow output is meant for straightforward analytics queries, including KQL. That matters because the same stream can feed a Spark notebook and other real-time consumers without forcing every downstream system to learn Debezium semantics.

The catch

This is preview. Act like it.

Preview is where features meet unpleasant reality: weird schemas, bad timing, broken assumptions, and the database that nobody documented properly. DeltaFlow may still be the right direction. It is not a blind cutover candidate.

Run it beside your current CDC path. Compare outputs. Change a source table. Watch what happens. Kill and restart the notebook path. See where the edges are before you let production depend on it.

Also, source coverage is still narrow. Mixed database estates are going to run split architectures for a while. DeltaFlow on the supported sources. Existing CDC plumbing everywhere else.

PostgreSQL teams have homework

The PostgreSQL connector doc is specific.

To enable CDC for PostgreSQL in this flow, Microsoft says you need:
– wal_level set to logical
– max_worker_processes set to at least 16
– a server restart after those changes
– replication permissions for the connecting admin user or table owner user

There is also a networking constraint. The database must be publicly accessible unless you use Eventstream connector virtual network injection. Miss that detail and your migration plan turns into a late-night fight with networking.

What to do now

Keep the rollout small and brutal.

Start with one supported source. Enable DeltaFlow. Pick “Analytics-ready events & auto-updated schema.” Route it to a Spark notebook destination. Then measure three things:
– How much parsing code vanished
– How much schema handling vanished
– How stable the preview behavior is under source changes

One more signal is worth noticing. In the same March 2026 feature summary, Microsoft listed the Eventstream SQL Operator as generally available. DeltaFlow itself is still preview, but the Eventstreams surface around it is getting more serious.

That is the moment to test. Not later, when everyone suddenly wants it in production at once.

Bottom line

DeltaFlow matters because it attacks the worst part of CDC work. Not the business logic. The plumbing.

For supported sources, that is real leverage for Fabric Spark teams. For unsupported sources, nothing changes yet.

So do the sensible thing. Test it early. Keep your current pipeline until the preview earns trust. Then decide whether DeltaFlow gets promoted from experiment to foundation.

This post was written with help from anthropic/claude-opus-4-6

Operationalizing Fabric’s February 2026 feature drop: what actually matters for Spark teams

Operationalizing Fabric's February 2026 feature drop: what actually matters for Spark teams

Microsoft’s monthly feature summaries have a familiar problem. They flatten every change into the same cheerful pitch. A new cell editor mode gets about the same oxygen as a moving security boundary. If you run Spark seriously on Fabric, that is useless. You need to know which items change architecture, which clean up the daily notebook grind, and which quietly add a new failure mode.

February’s release has all three. The headline is not “more features.” The headline is that Fabric keeps removing excuses for portal-driven, manually operated Spark environments. More of the platform can now be secured, composed, and managed through code. That is good news. It also means the easier Microsoft makes this, the more discipline you need on your side.

The change that actually alters architecture

CMK support for notebook code

This is the big one.

Fabric notebooks can now run inside CMK-enabled workspaces, with notebook content and associated notebook metadata encrypted at rest using customer-owned keys in Azure Key Vault. Microsoft is not vague about the coverage. The post calls out cell source, cell output, and cell attachments.

If your team has been splitting its development pattern because notebooks were the odd object out in a tighter security model, that split is no longer structurally required. Plenty of enterprises ended up with an awkward arrangement: secure workspaces for governed assets, then a side channel for notebook authoring and iteration. February closes that gap.

The payoff is boring in the best way. Fewer workarounds. Fewer places where permissions drift. Fewer security reviews where someone has to explain why the code path lives outside the workspace standard applied to everything else.

It also changes the migration conversation. Teams that avoided notebooks in regulated environments can revisit that decision. Teams already on notebooks can ask whether a separate architecture still buys them anything except paperwork.

The catch is operational, not conceptual. Keys rotate. Policies get tightened. When notebook content and metadata sit under the same CMK envelope, key management stops being an abstract security exercise and starts touching the authoring surface your engineers use every day. If you do not test rotation and recovery in a non-production workspace first, you are volunteering to learn in public.

The workflow fix Spark teams needed months ago

Python notebooks finally get %run

This was overdue.

PySpark notebooks had a workable modularity story. Python notebooks did not. If you wanted shared setup logic, common helper functions, or a standardized preamble, you either copied code between notebooks or invented a packaging scheme to compensate for a missing primitive.

Now Python notebooks support %run. You can reference and execute other notebooks in the same execution context, then directly use the functions and variables defined there. That is the difference between notebook code as a pile of local accidents and notebook code as something you can organize on purpose.

There is one limitation, and it matters: today %run in Python notebooks supports notebook items only. It does not yet run .py modules from the notebook resources folder. Microsoft says that support is coming soon. Fine. “Coming soon” is not an architecture. Build around notebook references now, and treat resource-folder module execution as a future upgrade if it arrives on time.

The immediate move for most teams is simple. Pull duplicated utility code into shared notebooks. Keep them small. Keep ownership clear. Do not turn %run into a dependency swamp where every notebook imports half the workspace and nobody can explain execution order without drawing a crime-scene diagram.

Version history now tells you where a change came from

This sounds like a minor quality-of-life improvement until you have to debug a bad deployment before the second cup of coffee.

Fabric notebook version history now labels the source of each saved version. Direct edits in the notebook, Git synchronizations, deployment pipeline updates, and publishing via VS Code all show up as distinct origins. That one label removes a stupid amount of ambiguity.

Before this, the question “what changed?” was followed by the more annoying question “through which path?” In a serious CI/CD setup, that distinction is the whole investigation. A manual portal edit points you to one human. A Git sync points you to a repo change. A deployment pipeline update points you to release plumbing. VS Code publishing points you somewhere else again. Same broken notebook, different root cause.

If your team uses more than one of these paths, update the runbook. The first step in notebook incident triage should now be checking the version source before anyone starts diffing content like a raccoon digging through a dumpster.

Full-size mode is small, but not trivial

Full-size mode lets a single notebook cell fill the workspace for editing. That is not glamorous. It is just useful.

Large SQL blocks, ugly transformation cells, and screenshared code reviews all get easier when the interface stops fighting you. Features like this do not make press-release people happy, but they do shave friction off work that happens every day. I would not redesign an architecture around it. I would absolutely use it.

The broader pattern hiding inside the release

Fabric is making Spark more reachable from both directions

Two February items matter together.

The new Microsoft ODBC Driver for Fabric Data Engineering gives external applications and ODBC-compatible tools a supported path into Spark SQL on Fabric. Microsoft describes it as ODBC 3.x compliant, backed by Livy APIs, and built for OneLake and Lakehouse data with Entra ID authentication, proxy support, session reuse, and Spark SQL coverage that looks designed for real workloads instead of demos.

Then there is Semantic Link 0.13.0. That release expands management coverage across lakehouses, reports, semantic models, SQL endpoints, and Spark. Microsoft is explicit about the direction: creating and managing lakehouses and tables, cloning and rebinding reports, refreshing and monitoring semantic models, and administering SQL and Spark settings from code.

Put those together and the platform’s direction is obvious. Fabric wants Spark environments that can be queried from outside and administered from inside code, without the portal as the center of the universe. That is the right direction. The portal is useful. The portal is not a control plane.

This is also where teams get themselves into trouble. The moment workspace operations become scriptable, governance stops being a policy deck and becomes a permissions design problem. If every engineer can programmatically create lakehouses, modify Spark settings, and rebind reports, then congratulations: you have built an accidental infrastructure platform. Maybe that is fine. Maybe it is a terrible idea. Decide before the scripts proliferate.

My bias is blunt. Treat Semantic Link as production infrastructure tooling, not as a convenience library. Set conventions early. Define who can do what. Log changes. Review the scripts that touch shared assets. Otherwise you will end up with beautiful automation and feral workspaces.

The quiet footgun in the admin section

Fabric identity limits now scale higher, but Fabric will not save you from bad math

Fabric now raises the default tenant limit for Fabric identities from 1,000 to 10,000. That is a real scale change, and for some organizations it removes an artificial ceiling that was starting to pinch.

It also lets admins set custom limits and manage them through the Update Tenant Setting REST API. Good. That is how this should work.

The problem is the warning Microsoft slips into the text: Fabric does not validate whether your custom limit fits within your Entra ID resource quota.

That means the setting feels authoritative while depending on an external quota boundary it does not enforce. In other words, the UI and API will happily let you declare ambition. Entra ID is the system that decides whether ambition has a permit.

So before anyone bumps the limit because “10,000 sounds better,” check the Entra side first. If you automate the setting, add that quota check to the automation. This is not exotic engineering. It is basic adult supervision.

What I would do this week

If you own Spark on Fabric, February’s release suggests a short, unromantic punch list.

  • Review whether CMK support lets you collapse any split workspace pattern built around notebook restrictions.
  • Start using %run in Python notebooks for shared helpers, but keep the dependency graph understandable.
  • Update notebook incident runbooks so version-source labels are part of first response.
  • Decide whether the ODBC driver and Semantic Link belong in your standard platform toolkit, then put guardrails around both before usage spreads.
  • Check Entra ID quotas before changing Fabric identity limits, especially if a script is going to do it for you.

That is the real shape of the month. A nicer notebook editor is fine. A new driver is nice. The deeper story is that Fabric keeps shifting Spark toward a model where security, reuse, and administration happen in code instead of in tribal knowledge and portal muscle memory. That is progress. It also means the teams that win will be the ones that pair new capability with restraint, because the platform is getting powerful enough to automate your mistakes at scale.

This post was written with help from anthropic/claude-opus-4-6

Operationalizing the semantic model permissions update for Fabric data agents

Operationalizing the semantic model permissions update for Fabric data agents

Permissions in data platforms have a remarkable talent for turning a two-minute job into a small municipal drama. You want one ordinary thing. The system hands you a form, a role, a workspace, another role, and, sooner or later, a person named Steve who is out until Thursday.

Starting April 6, 2026, Microsoft Fabric removes one of those little absurdities. Creators and consumers of Fabric data agents need only Read access on the semantic model to use it through a data agent. Workspace access is no longer required.

Small sentence. Large relief.

Why this matters

Fabric data agents use Azure OpenAI to interpret a user’s question, choose the most relevant source, and generate, validate, and execute the query needed to answer it. That source might be a lakehouse, warehouse, Power BI semantic model, KQL database, or ontology.

So the agent is already doing the interesting work. It is translating a human question into something a data system can answer. Requiring extra workspace access just to reach a semantic model added bureaucracy to the wrong layer.

The change, plainly

The official change is simple: beginning April 6, creators and consumers only need Read access on the semantic model to interact with it through a Fabric data agent. The older workspace access and Build permission hurdle disappears for this path.

If you have ever untangled access requests, you can probably hear the sigh from here.

What to do with that information

The first operational question is not “What new permission do I need?” It is “Which workspace grants exist only because the old rule forced them?”

Start there.

  • List the semantic models your data agents use.
  • Identify users or groups with workspace access granted only for those agent scenarios.
  • Test the new flow with a read-only user as April 6 approaches.
  • After the change lands, remove workspace access that no longer serves a separate purpose.

This is not glamorous work. Neither is plumbing, and everyone suddenly develops strong feelings about plumbing when it breaks.

The part people will miss

One detail matters more than the permission change itself. When a Fabric data agent generates DAX for a semantic model, it relies only on the model’s metadata and Prep for AI configuration. It ignores instructions added at the data agent level for DAX query generation.

That puts responsibility where it belongs: on the model.

If a business user asks a sensible question and gets a crooked answer, the fix is usually not a cleverer agent prompt. The fix is to improve what the model gives the agent to work with: the metadata and the Prep for AI setup.

That is the real operational shift. Access gets easier. Model preparation matters more.

A sensible rollout

If you own Fabric governance, keep the rollout dull and methodical.

  • Review which data agents rely on semantic models.
  • Retest those scenarios with users who have Read access on the model and no workspace access.
  • Inspect the models that produce weak DAX and improve the metadata and Prep for AI configuration they expose.
  • Clean up workspace permissions that were granted only to satisfy the old requirement.

Nobody frames that checklist and hangs it in the lobby. It still gets the job done.

The useful conclusion

The best part of this update is that it removes a fake dependency. A data agent that can answer questions from a semantic model should not require a side trip through workspace permissions.

The catch is that the agent still cannot invent a well-prepared model out of thin air. Fabric has made access lighter. It has also made the remaining truth easier to see: if you want better answers, the semantic model has to be ready for the job.

Which is, frankly, how this should have worked all along.

This post was written with help from anthropic/claude-opus-4-6

ExtractLabel just changed how your Spark pipelines should handle unstructured data

ExtractLabel just changed how your Spark pipelines should handle unstructured data

Every data engineer eventually inherits the same cursed pipeline.

Upstream sends you a blob of human text. Somewhere in that blob are the exact facts your downstream systems need: product name, issue category, requested resolution, timeline, who did what, and when. The facts are there. They are just buried in prose written by sleep-deprived humans, copied from emails, and occasionally typed from a phone in an airport parking lot.

For years, we handled this with a pile of hacks:

  • Regex that works until one user adds a comma
  • Hand-rolled NER that drifts quietly into uselessness
  • LLM prompts that return valid JSON on Monday, improv theater on Tuesday

Then we pretend this is fine by writing 300 lines of “normalization” code downstream, plus defensive checks, plus retry logic, plus enough if statements to make your future self hate your past self.

That is the old world.

ExtractLabel is the first Fabric AI Functions primitive that treats extraction like a contract instead of a vibe. You define the shape once in JSON Schema. The extraction step returns that shape. Your pipeline gets predictable structure instead of model improv.

If you run Spark workloads in Fabric, this matters immediately.

What AI Functions already gave you (and where it fell short)

Before ExtractLabel, the quick path looked like this:

df["text"].ai.extract("name", "profession", "city")


For exploration, that is great. For production, it is a trap.

Prototype extraction asks, “Can the model find useful fields?”
Production extraction asks, “Can every downstream consumer trust type, shape, and vocabulary every single run?”

Those are different questions.

The basic label call is lightweight and convenient, but it leaves the hardest part unsolved: schema discipline. If your routing logic expects one of four categories, free-form output creates entropy. If your analytics expects arrays, and extraction returns comma-separated strings, you are writing cleanup code forever. If optional fields are not explicitly nullable, models tend to fill blanks with plausible nonsense.

The model understanding was never the bottleneck. Contract reliability was.

ExtractLabel: the schema contract your pipeline needs

ExtractLabel gives you an explicit schema boundary between unstructured input and structured output. In pandas you import from synapse.ml.aifunc; in PySpark you import from synapse.ml.spark.aifunc. The core pattern is the same: define one label with object properties, requirements, and constraints.

Concrete example, using warranty claims:

from synapse.ml.aifunc import ExtractLabel

claim_schema = ExtractLabel(
    label="claim",
    max_items=1,
    type="object",
    description="Extract structured warranty claim information",
    properties={
        "type": "object",
        "properties": {
            "product_name": {"type": "string"},
            "problem_category": {
                "type": "string",
                "enum": ["defect", "damage_in_transit", "missing_part", "other"],
                "description": "defect=stopped working or malfunctioning, damage_in_transit=arrived damaged, missing_part=something not included"
            },
            "problem_summary": {
                "type": "string",
                "description": "Max 20 words. Summarize the core issue."
            },
            "time_owned": {"type": ["string", "null"]},
            "troubleshooting_tried": {
                "type": "array",
                "items": {"type": "string"}
            },
            "requested_resolution": {
                "type": "string",
                "enum": ["replacement", "refund", "repair", "other"]
            }
        },
        "required": ["product_name", "problem_category", "problem_summary",
                     "time_owned", "troubleshooting_tried", "requested_resolution"],
        "additionalProperties": False
    }
)

df[["claim"]] = df["text"].ai.extract(claim_schema)


Input text:

“The smart thermostat stopped turning on after 12 days. I tried a reset and new batteries. Please replace it.”

Structured output:

{
    "product_name": "smart thermostat",
    "problem_category": "defect",
    "problem_summary": "Thermostat stopped turning on after 12 days",
    "time_owned": "12 days",
    "troubleshooting_tried": ["reset", "new batteries"],
    "requested_resolution": "replacement"
}


That is the difference: you are no longer extracting “some fields.” You are producing an object your systems can rely on.

The five schema features that actually matter

Most teams will over-focus on “LLM extraction” and under-focus on schema design. That is backwards. The model is only half the system. The schema is what makes it production-safe.

1) Nullable types

Use explicit nullable definitions for fields that may not exist in the source text:

"time_owned": {"type": ["string", "null"]}


If you do not allow null, the model is pressured to invent. Nullable fields reduce that pressure.

2) Enums for category control

When downstream logic expects bounded values, enforce them with enum.

That turns category assignment from fuzzy language output into controlled vocabulary. If your pipeline routes by problem_category, this is non-negotiable.

3) Arrays for true multi-value extraction

If a claim can include multiple troubleshooting actions, represent it as an array. Do not accept packed strings and split later.

Array semantics belong in extraction, not in cleanup jobs.

4) Descriptions as extraction instructions

Descriptions are not decorative comments. They are guidance for the extraction step.

Use them to define edge behavior, clarify enum intent, and enforce concise summaries. Most quality gains come from this field, not from prompt wording elsewhere.

5) Nested objects for real-world structure

Complex payloads are rarely flat. If your domain includes sub-entities, model them as nested objects now. Flattening everything into top-level strings feels easier in week one and becomes technical debt by week six.

What this means for your Spark pipelines right now

If your team already runs text extraction in Fabric pipelines, ExtractLabel gives you a clean migration path with immediate payback in reliability.

Practical rollout plan:

  1. Find the pain first. Audit extraction steps where downstream code spends time repairing output shape, casing, and categories. Those are your highest-ROI migrations.
  2. Version schemas like code. Store schema definitions in source control with explicit version tags. Treat schema changes as contract changes, not casual edits.
  3. Use one extraction contract per domain task. Do not build one giant universal schema. Warranty claims, support tickets, and contract clauses deserve separate schemas with domain-specific enums and guidance.
  4. Prefer model-based schema authoring as complexity grows. Once schemas get large, hand-editing JSON gets brittle. Define structures in typed Python models and generate JSON Schema from there. You get stronger review discipline and fewer silent mistakes.
  5. Build an evaluation harness before broad rollout. ExtractLabel enforces structure; it does not guarantee semantic correctness. Keep a labeled sample set, score extraction quality regularly, and review drift.
  6. Tune operational settings with real workload telemetry. Concurrency, retry behavior, and throughput limits should be validated in your environment, not assumed from defaults. Measure error columns and latency under realistic load before declaring victory.

Verify runtime, capacity, and governance prerequisites against current Fabric documentation in your tenant before rollout. Platform details move. Your production runbooks should not rely on stale assumptions.

Migration risks worth thinking about

ExtractLabel is strong, but this is still LLM-powered extraction. You need grown-up operating discipline.

Model behavior drift

Even with stable schema shape, semantic interpretation can shift over time. A phrase that mapped to defect last month might map to other after a model update.

Mitigation: maintain a regression set and run periodic quality checks. Contract shape is necessary. Accuracy monitoring is mandatory.

Cost surprises at volume

Row-wise AI extraction scales linearly with data volume. Teams underestimate this, then panic when ingestion spikes.

Mitigation: test on representative daily volume, not a toy sample. Budget for peak days, not median days.

Schema evolution pain

You will add fields. You will split categories. You will regret one enum name. That is normal.

Mitigation: include schema version metadata in outputs and plan how downstream consumers handle mixed historical versions.

False confidence from “valid JSON”

Teams see valid typed output and stop questioning semantics. That is how bad extractions get into trusted dashboards.

Mitigation: sample manually, review periodically, and keep humans in the QA loop for high-impact fields.

When to use ExtractLabel vs. other approaches

Use ExtractLabel when all of these are true:

  • Input is unstructured text
  • Output must be typed and schema-conforming
  • You need extraction embedded in Fabric data workflows

Keep regex when the task is deterministic and mechanical (IDs, fixed-format dates, known token patterns).

Keep specialized NER pipelines when domain vocabulary is unusual, latency requirements are strict, or inference cost constraints are severe.

Use document-native extraction tools when layout matters (forms, scans, tables in images/PDFs). Text-column extraction will not recover geometry it never saw.

If your instinct is “we can just prompt harder,” stop. That is how you build a fragile system that passes demos and fails operations.

The bottom line

ExtractLabel moves Fabric extraction from improvisation to contracts.

The shiny part is one line of code:

df[["claim"]] = df["text"].ai.extract(claim_schema)

The valuable part is everything you encode in the schema: allowed values, nullability, nested structure, and descriptive guidance for edge cases.

Do that work once, and your downstream pipeline stops behaving like a cleanup crew.

Less duct tape, more reliable data.


This post was written with help from anthropic/claude-opus-4-6

What “Recent data” in Fabric means for Spark teams when time is the real bottleneck

At 8:07 a.m., nobody on a data engineering team is debating architecture purity. You’re trying to get back to the exact source you were fixing yesterday before another downstream notebook fails and somebody asks for an ETA.

That’s the problem Microsoft Fabric’s Recent data feature targets.

The feature landed in the February 2026 Fabric update and is currently in preview. It sounds small: Dataflow Gen2 remembers the specific items you used recently — tables, files, folders, databases, and sheets — and lets you load them directly into the editing canvas. For Spark-heavy teams, though, this is less of a UX tweak and more of a way to stop bleeding time in the first mile of work.

And yes, it’s still a preview feature. Treat it like a mountain route in unstable weather: useful, fast, and not something you trust blindly.

Why Spark teams should care about a Dataflow feature

A lot of Spark teams still frame Dataflow Gen2 as somebody else’s tool. That framing is outdated.

Dataflow Gen2 automatically creates staging Lakehouse and Warehouse items in your workspace. If your team’s workflow includes Dataflow-based ingestion and Spark-based transformation, the handoff between those steps is real. It’s your daily route.

Here’s the hard lesson: if your ingestion layer touches Dataflow Gen2, then UI friction inside Dataflow is your Spark team’s problem too.

What to do about it:

  • Write down your ingestion handoffs in plain language: source to Dataflow Gen2 to staging Lakehouse/Warehouse to Spark notebooks.
  • Mark where engineers repeatedly reconnect to the same sources. That’s where Recent data pays off first.

What Recent data changes under pressure

Recent data does one thing that matters: it remembers specific assets, not just abstract connections.

When you return to a fix, you’re not restarting the expedition from base camp. You get dropped closer to the problem. You can pull the item directly into the editing canvas and keep moving.

For teams, this changes the rhythm of incident response and iteration:

  • You get back to source-level corrections faster.
  • You reduce the chance that someone reconnects to the wrong similarly-named object while moving too fast.
  • You spend less team energy on navigation and more on data correctness.

None of this is glamorous. It’s also exactly where engineering throughput gets won.

Try this: during your next defect cycle, track one metric for a week — time from “issue found” to “source query/table reopened in Dataflow Gen2.” If that number drops after using Recent data, keep leaning in. If it doesn’t, your bottleneck is elsewhere.

What this feature doesn’t rescue you from

Teams love to over-credit new features. Recent data is a navigation accelerator. It’s not governance. It’s not validation. It’s not a replacement for naming discipline. And because it’s in preview, it’s not a foundation for critical operational assumptions.

If your source naming is chaotic, Recent data will surface chaos faster.

If your validation is weak, Recent data will help you ship mistakes sooner.

If your runbooks are vague, Recent data won’t magically teach new engineers what “correct” looks like.

Pair it with a minimum Spark validation pass after ingestion updates: schema check, null expectation, row-count sanity check. Keep this lightweight and repeatable. The point is fast feedback, not ceremony.

Preview discipline: run this like a survival checklist

Because Recent data is in preview, your team should operate with explicit guardrails.

Test in development first. Don’t roll workflow assumptions into production muscle memory before your team has used the feature in real edits.

Keep a source-of-truth map. Recent data is convenience. Your documented source map is control. Keep both.

Standardize names now. If a human can confuse two source objects at a glance, they will. Fix names before speed amplifies mistakes.

Define a fallback path. If the recent list doesn’t have what you need, nobody should improvise. Document the manual reconnect path and keep it current.

Review preview behavior monthly. If the feature behavior shifts while in preview, your team should notice fast and adjust intentionally. Assign one owner for “preview watch” each month. Their job: test the core flow, confirm assumptions still hold, alert the team if anything drifts.

The operating model for Spark leads

If you lead a Spark data engineering team, the decision is straightforward.

Use Recent data. Absolutely use it. But use it like a rope, not like wings.

A rope gets you through rough terrain faster when the team is clipped in, communicating, and following route discipline. Wings are what people imagine they have right before they step into empty air.

In practice:

  • Adopt the feature for speed.
  • Keep your documentation for continuity.
  • Keep naming conventions strict for safety.
  • Keep Spark-side validation for quality.
  • Treat preview status as a real risk signal, not legal fine print.

That combination is where this feature becomes meaningful. Not because it’s flashy. Because it removes repeated friction at exactly the point where your team loses focus, burns time, and compounds small mistakes.

In data engineering, the catastrophic failures usually start as tiny oversights repeated at scale. Recent data removes one class of those oversights — the constant re-navigation tax — but only if you wrap it in disciplined operating habits.

One less avoidable stumble on steep ground, so your team can spend its strength on the parts of the climb that actually require judgment.


This post was written with help from anthropic/claude-opus-4-6