If you’ve spent any real time in notebooks, you’ve felt it: the “why am I doing this again?” moment. You start a session, install the same libraries, chase a version mismatch, restart a kernel, and finally get back to what you actually came to Fabric to do.
Microsoft Fabric Environments are a strong answer to that pain. They pull your Spark runtime choice, compute settings, and library dependencies into a reusable, shareable artifact you can attach to notebooks and Spark Job Definitions. And with the latest previews—Azure Artifact Feed support inside Environments and Fabric Runtime 2.0 Experimental—it’s clear Microsoft is investing in making Spark development in Microsoft Fabric more repeatable and more “team ready.”
There’s a catch, though: once you introduce Private Link (and the networking controls that tend to come with it), some of the most convenient paths close off. So the story becomes less about “click to go faster” and more about “choose your trade-offs intentionally.”
In this post, I’ll cover what Fabric Environments are, what’s new in the previews (Artifact Feeds + Runtime 2.0), why Environments speed up real work, and where Private Link limits your options—and what you can do about it.
Fabric Environments: the missing layer between notebooks and “real” engineering
A Fabric Environment is a consolidated item for hardware and software settings. In plain terms, it’s where you define:
- your Spark compute choices (including runtime),
- your libraries (built-in + what you add),
- and lightweight resources you want accessible when the Environment is attached.
Two details matter for day-to-day productivity:
Environments attach directly to notebooks and Spark Job Definitions. When attached, your workloads can access the Environment’s libraries, compute configurations, and resources—without re-declaring the same setup in every artifact.
Environments can be set as a workspace default. Admins can attach an Environment as the workspace default so new work inherits the runtime, compute settings, and libraries automatically. That’s not just governance; it’s fewer “setup minutes” burned per notebook.
There’s also an operational nuance that’s easy to miss until you hit it: library and compute changes aren’t fully effective until you Publish the Environment, and publishing may take time—especially when libraries change.
Preview: Azure Artifact Feed support in Fabric Environments
This is the preview that will make a lot of teams lean forward: Fabric Environments can install Python libraries not only from public sources (PyPI/Conda), but also from private repositories like Azure Artifact Feed.
A quick refresher: Azure Artifacts feeds are the organizational construct in Azure DevOps used to store, manage, and share packages with controlled access (and they can host multiple package types).
Fabric’s implementation has a couple of important characteristics:
- Credentials aren’t stored directly in Fabric. The documentation is explicit: “directly storing the credential is forbidden,” and the connection must be set up through a Data Factory Connector connection.
- You then reference the connection via a Connection ID in your Environment’s YAML, instead of embedding a credentialed
--index-url. - When you publish the Environment, Fabric reads packages from the private repo and persists them in Fabric; if the feed updates, you republish to pull changes forward.
Here’s the core idea in YAML form (this is conceptually what the docs illustrate—notice the move from a URL to a connection ID):
dependencies:
- pip:
- your-internal-lib==1.2.3
- --index-url <YOUR_CONNECTION_ID>
That’s a very DevOps-friendly direction: a central feed, versioned internal packages, and an Environment that becomes the repeatable “runtime contract” for your notebooks.
The limitation you need to know upfront
This preview is also where the Private Link story starts to bite:
Installing libraries from Azure Artifact Feed is currently supported in Spark 3.5, and not supported in Private Link or outbound access protection enabled workspaces.
If your organization is moving toward Private Link + locked-down outbound, plan on needing an alternate library strategy (more on that below).
Preview: Fabric Runtime 2.0 Experimental is here—and it changes the baseline
Fabric Runtime 2.0 Experimental (Preview) is now documented as an experimental preview runtime with major platform upgrades: Spark 4.0, Delta Lake 4.0, Python 3.12, Java 21, Scala 2.13, and Azure Linux 3.0.
Two practical ways to use it are called out:
- enable it at the workspace level for all Spark workloads, or
- enable it at the Environment level so only specific notebooks/jobs use it (overriding the workspace default).
This Environment-level switch is a big deal. It means you can test Runtime 2.0 intentionally—without “surprising” every notebook in the workspace.
Runtime 2.0 is powerful, but it won’t feel faster in every way (yet)
One of the most honest lines in the Runtime 2.0 documentation is about startup time:
Spark 2.0 sessions can take around 2–5 minutes to start because starter pools aren’t part of the early experimental release. (Of course, if you can’t use starter pools – say because you’re using Private Link, this is mostly a wash)
So while Runtime 2.0 unlocks the newer Spark/Delta/Python stack, interactive iteration may actually feel slower until the runtime matures.
And, as you’d expect for a preview: there are feature gaps (for example, R not supported, Spark Advisor unavailable, and some integrations/connectors not supported in this early release).
If you’re experimenting, that’s fine. If you’re building production workflows, treat “Experimental (Preview)” exactly as Microsoft describes previews: limited capabilities, best-effort support, and not meant for production use.
Why Environments make Fabric “feel” faster
When people say “speed,” they often mean runtime performance. In practice, the bigger drag on most teams is workflow latency: the setup friction and inconsistency that slows iteration.
Environments reduce that friction in a few concrete ways:
They eliminate repeated setup across notebooks. Attach the Environment and your libraries + compute configuration come along with it. That’s less “pip install, restart, retry” time per session.
They make standardization easy. When you set an Environment as the workspace default, new work inherits it automatically, and only workspace admins can update the default Environment—which keeps teams from drifting into ten subtly different dependency stacks.
They make upgrades safer. Runtime changes require republishing, and incompatible libraries/configurations can fail publishing. That sounds annoying—but it’s also a forcing function that surfaces “this upgrade will break you” early, rather than in the middle of a scheduled job.
This is why I describe Environments as an enablement feature for data engineering: they turn Spark work in Fabric from “personal notebook state” into a reusable, reviewable asset.
Where Private Link changes the math (and limits your options)
Private Link is often non-negotiable in regulated environments. But it changes what “easy” looks like.
Private Link: what it’s doing at a high level
Workspace-level private links map a workspace to a virtual network via Azure Private Link, and can restrict public internet access so only approved VNets can access the workspace via private endpoints.
Fabric documents supported item types for workspace-level private links, and that list explicitly includes Notebooks, Spark Job Definitions, and Environments. So Environments still “work” in a Private Link world.
The first hidden cost: “first Spark job” provisioning time
When Private Link is enabled, the first Spark job in the workspace triggers VNet provisioning, which can take ~10–15 minutes. Fabric also notes that Environment publishing runs as a Spark job—so your first publish after enabling Private Link may be delayed if it’s the first Spark workload to run.
That’s not a deal-breaker, but it’s an operational reality worth documenting for your team.
The second hidden cost: you lose the easy library paths
This is the big one.
The Environment library management documentation explicitly states that installing libraries from Azure Artifact Feed is not supported in Private Link or outbound access protection enabled workspaces.
And when outbound network security is enabled, Fabric blocks access to public repositories like PyPI and conda, which prevents installing public libraries or downloading dependencies.
So, in a locked-down network, your choices narrow to strategies that don’t require reaching out to the public internet at runtime.
Microsoft’s guidance here is refreshingly direct:
- Recommended: upload packages and dependencies as custom libraries into the Environment (wheels, jars, etc.).
- Alternative: host a PyPI mirror on an Azure Storage account protected behind your org vNet, and access it via private managed endpoints; then point
pipat that internal mirror using--index-url.
This is the moment where Private Link stops being “just a networking feature” and becomes an architectural decision that reaches all the way into dependency management.
The third constraint: reusing Environments across workspaces isn’t frictionless
Fabric allows you to attach an Environment from another workspace, but both workspaces must have the same capacity and network security settings—otherwise the session fails to start.
That means a common pattern—“build the Environment in an open dev workspace and reuse it in a locked-down prod workspace”—may not work if the security posture differs. Private Link can indirectly force you to duplicate (or re-build) Environments inside the secured boundary.
The fourth constraint: Losing starter pools
This is a problem that seems trivial when you’re planning, but it imposes a constant tax throughout fabric. Every operation takes from 3-5 minutes to start as the environment is provisioned, because those starter pools can’t be prebuilt to environment standards and shared. This becomes a tax on development, on integration, and on the usage of spark at all. If you plan for it, it’s managable, but if you only notice it once you start your deployments, it can cause a tremendous amount of rework.
A practical way to think about the trade-offs
If you’re trying to pick a path without turning this into a three-month platform initiative, here’s the simplest framing I’ve found:
- If your workspace can reach public repos, Environments + public libraries are the fastest to iterate with.
- If you need private packages and your workspace isn’t Private Link / outbound-restricted, the Azure Artifact Feed preview is the cleanest internal option.
- If Private Link and outbound restrictions are required, plan on custom library uploads or an internal mirror—because the convenience features are intentionally blocked.
There isn’t a universally “right” choice—only the one that matches your security requirements and your team’s tolerance for maintaining dependency infrastructure.
Conclusion: Environments are the new center of gravity—design them like it
Here’s what we covered:
- Fabric Environments centralize Spark runtime, compute configuration, libraries, and resources into a reusable artifact you can attach to notebooks and Spark jobs.
- Two big previews are expanding the story: Azure Artifact Feed support for installing private Python libraries (with meaningful limitations), and Fabric Runtime 2.0 Experimental for teams testing the Spark 4.0 / Delta 4.0 stack.
- Environments don’t just improve consistency; they reduce workflow friction—which is why they can make Fabric feel faster for real teams.
- Private Link is valuable, but it narrows your dependency management options and can introduce operational delays, pushing you toward pre-built packages or internal mirrors.
The action I’d recommend is straightforward: pick one workspace and treat its Environment as your “golden path.” Decide whether it lives in an open-outbound world or inside a Private Link boundary, and then build your library strategy around that decision—not the other way around.