Azure Databricks is split into a control plane (the brains, run by Databricks in their subscription) and a compute plane (the muscle, where your data is processed — classic in your subscription/VNet, or serverless in Databricks'). Your data lives in your ADLS Gen2 and is read directly by compute — it never flows through the control plane.
An airport with exactly three doors. Control plane = control tower (directs, never holds cargo). Compute plane = runway + aircraft (classic = your runway; serverless = rented runway). Databricks runs the brain in its own subscription; your data is processed in the compute plane and never leaves your storage; connections only ever point outward from compute to control.
| Path | Who talks to whom | Analogy | Hardened by |
|---|---|---|---|
| ① User → Databricks | Browser / BI / REST → workspace URL | Front door | IP access lists · front-end Private Link |
| ② Compute ↔ Control | Cluster phones home to be managed | Staff intercom | SCC · back-end Private Link · (serverless: backbone) |
| ③ Compute → Storage | Cluster reads/writes your ADLS data | Loading dock | Storage firewall · Service/Private Endpoint · NCC |
"Customer data stays in the customer's storage and is processed in the compute plane; the control plane holds metadata and orchestration only. Classic compute ↔ control and all serverless traffic ride the Microsoft backbone — not the public internet."
Two sets of machines, two parties, two subscriptions. The control plane is the brain Databricks runs; the compute plane is where your data is processed. Switch the diagram between classic and serverless and click any box to see what it is and why it's there.
Under Secure Cluster Connectivity (No Public IP), cluster VMs have no public IPs and your VNet has no open inbound ports. The cluster dials out to the SCC relay on 443 and the control plane sends instructions back down that tunnel — it never dials in. "No inbound ports" isn't magic; it's a reversed connection.
| Dimension | Classic | Serverless |
|---|---|---|
| Runs in | Your subscription / VNet | Databricks-owned subscription |
| Network you control | The VNet (managed or injected) | None — no customer VNet |
| Public IPs on compute | No (NPIP) | No |
| Secure egress with | NSG / UDR / NAT / Firewall / PE | NCC + network policies |
| Startup | Minutes | Seconds (pre-warmed) |
Terraform (azurerm) — the one flag that defines the boundary. Full VNet-injection IaC is the Stage 3 hands-on artifact.
resource "azurerm_databricks_workspace" "this" {
name = "adb-arch-demo"
resource_group_name = "adb-rg"
location = "eastus"
sku = "premium" # unlocks Private Link / CMK / IP ACLs later
custom_parameters {
no_public_ip = true # THE boundary: no public IPs, no inbound ports;
} # clusters dial OUT to the SCC relay on 443
}
Portal: Create → Azure Databricks → Networking → Secure Cluster Connectivity (No Public IP) = Yes. Verify: workspace → Managed Resource Group → a cluster VM → Properties → Networking → Public IP is empty.
A classic workspace is labelled a "Hybrid workspace" in the Portal. And after 2026-03-31, new Azure VNets default to no outbound internet — a new workspace needs an explicit NAT Gateway or clusters won't start.
Given the two planes, only three connections carry traffic, and almost every control protects one of them. Switch the diagram between the three paths — the highlighted (orange/green) arrow is the active path; click any box for the "what + why."
Path ② (classic) and all serverless traffic are already on the Microsoft backbone. Private Link/NCC just remove the last public-IP hop the auditor cares about — it doesn't "get you off the internet," because you mostly already are. This stops customers over-buying Private Link.
| ① User → DBX | ② Compute ↔ Control | ③ Compute → Storage | |
|---|---|---|---|
| Direction | Inbound to control plane | Outbound from compute (SCC reverses it) | Outbound from compute |
| Classic control | IP access list / front-end PL | SCC + VNet injection, back-end PL | Storage firewall + Service/Private Endpoint |
| Serverless control | Same (front-end PL / IP ACL) | Managed, backbone + TLS (no SCC) | NCC service tag / NCC private endpoint |
| Key port(s) | 443 | 443 (SCC); back-end PL also 6666, 8443–8451, 3306 | 443 to storage |
By 2026-06-09, a storage account that allowlists serverless must onboard to an
Azure Network Security Perimeter (NSP) and allow the
AzureDatabricksServerless.<region> service tag — the older "allow serverless subnet IDs"
pattern is retiring.
Path ① lock the front door + IP allowlist · Path ③ default-deny storage firewall. Path ② is set at workspace creation (see 2.1); full VNet-injection/Private Link IaC is the Stage 3–4 hands-on artifact.
resource "azurerm_databricks_workspace" "this" {
sku = "premium" # IP access lists / Private Link need Premium
public_network_access_enabled = false # ① reject public access (front-end PL required)
}
# Path ③ — default-deny storage firewall + free Service Endpoint on the workspace subnet
resource "azurerm_storage_account_network_rules" "adls" {
default_action = "Deny" # ③ default-deny
virtual_network_subnet_ids = [azurerm_subnet.container.id] # allow only the workspace subnet
}
Azure Databricks is a first-party Azure resource (Microsoft.Databricks/workspaces).
One create lands resources in two resource groups, and the
account → workspace → metastore spine is the governance backbone. Switch the diagram between the
two resource groups and the governance spine.
Azure RBAC (Contributor/Owner) creates the workspace resource; a Databricks account admin (bootstrapped by an Entra ID Global Administrator) governs the account + metastore. Granting one does not grant the other. And deleting the managed RG's workspace storage account makes the workspace unrecoverable — lock it.
| Concern | Workspace storage / DBFS root | Unity Catalog + ADLS Gen2 |
|---|---|---|
| Governance | Workspace-scoped, coarse | Central metastore, fine-grained grants, ABAC |
| Lineage & audit | None for raw paths | Full lineage + system.access audit |
| Status | Deprecated / legacy | Recommended, GA |
resource "azurerm_databricks_workspace" "this" {
name = "adb-workspace"
resource_group_name = "adb-rg"
location = "eastus"
sku = "premium" # Standard tier is EOL 2026-10-01
managed_resource_group_name = "adb-managed-rg" # workspace storage/identity land here (read-only to you)
public_network_access_enabled = true # set false + Private Link later (Stage 4)
custom_parameters { no_public_ip = true } # SCC / NPIP
}
Then Account Console (accounts.azuredatabricks.net) → create a region-matched
metastore → assign workspaces. One metastore per region.
Start free, step up only when mandated. SCC + VNet injection (Path ②) and storage firewall + Service Endpoint (Path ③) cost nothing and are backbone-private. Add Private Link / NCC private endpoints only when a regulator demands no public-IP hop or on-prem/cross-peering reach. Premium + Unity Catalog-on-ADLS is the non-negotiable baseline.
| Customer asks… | Architect answers… |
|---|---|
| "Does our data ever touch the control plane / leave our subscription?" | No — business data stays in your ADLS Gen2; the control plane holds metadata + orchestration only. |
| "Does traffic hit the public internet between clusters and Databricks?" | No — classic compute ↔ control is the backbone (SCC relay, outbound 443); serverless ↔ control is always backbone. |
| "Can we get a stable egress IP for our allowlist?" | Yes for classic via Azure NAT Gateway. Serverless IPs are dynamic — use the AzureDatabricksServerless service tag / NCC. |
| "We put an NSG on everything — where for serverless?" | You can't; there's no customer VNet. That's exactly what NCC is for (Stage 5). |
| "Do we need Premium?" | Yes for any real customer — Standard is EOL 2026-10-01 and Private Link / CMK / IP ACLs / CSP are Premium-only. |
Post-2026-03-31, new Azure VNets have no default outbound, so the cluster can't reach the SCC relay.First check: NAT Gateway (or UDR→firewall) on the compute subnets.
Under NPIP, compute VMs get none.First check: cluster VM → Properties → Networking → Public IP is empty.
They allowlisted the SCC relay by raw IP; Databricks rotates the IPs behind the relay FQDNs.First check: allowlist the relay FQDNs, not IPs.
A classic subnet-ID rule was applied to serverless.First check: NCC bound + storage firewall allows AzureDatabricksServerless.<region> / NCC PE.
Paths ①–② locked, Path ③ forgotten.First check: storage account → Networking → public access still "all networks"?
dbfs:/ pathsNew accounts ship without DBFS root.First check: migrate to a UC volume / external location — don't re-enable DBFS.