Retiring a workspace looks like one az command. But deleting it also deletes its managed resource group, including the DBFS root storage account, and you can't undo that. Jobs in other systems may still call it, and the access connectors, private endpoints and Unity Catalog bindings it used are left behind. Work through this checklist in order, and record the evidence for each step in the change ticket.
Caution
Deleting an Azure Databricks workspace deletes the managed resource group (
databricks-rg-...) and everything in it, including the DBFS root storage account. Anything written todbfs:/paths that aren't mounts (for exampledbfs:/FileStore,dbfs:/user/hive/warehousemanaged tables in the legacy Hive metastore) is gone. Copy it out first.
1. Identify the workspace
az extension add --name databricks --upgrade
az databricks workspace show -g rg-dbx-legacy -n dbx-legacy-weu -o json \
| jq '{id, workspaceUrl, workspaceId, managedResourceGroupId, sku: .sku.name, location}'
Record workspaceId (the numeric ID used in system tables), the URL and the managed resource group ID. Confirm this is the workspace you mean to delete. Names like dbx-prod and dbx-prd are easy to mix up.
- Workspace ID, URL, subscription and managed resource group recorded
- Owner and business sign-off named in the ticket
2. Prove it's not in use
Run these from a different workspace attached to the same metastore, so you can keep checking after the workspace is frozen.
-- Spend in the last 30 days, by product
SELECT billing_origin_product, sku_name, ROUND(SUM(usage_quantity), 1) AS dbus
FROM system.billing.usage
WHERE workspace_id = '1234567890123456'
AND usage_date >= current_date() - INTERVAL 30 DAYS
GROUP BY ALL
ORDER BY dbus DESC;
-- Who is still signing in or calling the API
SELECT user_identity.email, service_name, COUNT(*) AS events, MAX(event_time) AS last_seen
FROM system.access.audit
WHERE workspace_id = '1234567890123456'
AND event_date >= current_date() - INTERVAL 30 DAYS
GROUP BY ALL
ORDER BY last_seen DESC;
Service principals in the audit output usually mean external callers such as Data Factory linked services, Power BI gateways, CI pipelines or apps. Search for the workspace URL in their configs:
# ADF linked services pointing at this workspace
az datafactory linked-service list -g rg-adf --factory-name adf-prod -o json \
| jq -r '.[] | select((.properties.typeProperties.domain // "") | test("adb-1234567890123456")) | .name'
- No scheduled jobs, pipelines or warehouses have consumed DBUs in 30 days (or every consumer has an agreed migration target)
- Every principal in the audit output is identified and contacted
- ADF, Power BI, Logic Apps, CI/CD and app configs no longer reference the workspace URL
3. Freeze it
Freeze the workspace before you delete it. Leave it frozen for one or two business cycles, so anything you missed fails without losing data.
# Pause every scheduled job
databricks jobs list -p legacy -o json | jq -r '.[] | select(.settings.schedule != null) | .job_id' \
| while read id; do
databricks jobs get "$id" -p legacy -o json \
| jq '{job_id, new_settings: {schedule: (.settings.schedule + {pause_status: "PAUSED"})}}' > /tmp/upd.json
databricks jobs update "$id" -p legacy --json @/tmp/upd.json
done
# Stop running compute
databricks clusters list --cluster-states RUNNING -p legacy -o json | jq -r '.[].cluster_id' \
| xargs -I{} databricks clusters delete {} -p legacy
databricks warehouses list -p legacy -o json | jq -r '.[] | select(.state=="RUNNING") | .id' \
| xargs -I{} databricks warehouses stop {} -p legacy
Warning
Use
jobs update(a partial update), as written.jobs resetreplaces all job settings, so sending only the schedule would wipe the tasks. Test the loop on one job first. Jobs with file-arrival or continuous triggers have noscheduleblock, so pause those in the UI or update theirtrigger/continuoussettings instead.
To block interactive use as well, add a restrictive IP access list or remove the workspace-access entitlement from the users group. Both are easy to reverse.
- All schedules, triggers and continuous jobs paused; pipelines stopped
- Clusters and warehouses stopped; freeze date and planned delete date announced
4. Save code and configuration
mkdir -p export/legacy
databricks workspace export-dir /Workspace ./export/legacy/workspace -p legacy
databricks jobs list -p legacy -o json > export/legacy/jobs.json
databricks clusters list -p legacy -o json > export/legacy/clusters.json
databricks cluster-policies list -p legacy -o json > export/legacy/policies.json
databricks secrets list-scopes -p legacy -o json > export/legacy/secret-scopes.json
Export the full settings of each job with databricks jobs get <id> and keep it with the export. Secret values can't be exported. Key Vault-backed scopes keep their values in Key Vault, but values in Databricks-backed scopes are lost when the workspace is deleted, so make sure their owners have them stored somewhere else.
- Workspace tree exported, or confirmed to be in Git (Git folders have pushed all branches)
- Job, cluster, policy, pool and warehouse definitions saved
- Owners of Databricks-backed secret scopes confirmed they have the values
5. Save data that lives inside the workspace
Unity Catalog managed and external tables live in metastore or catalog storage, which deleting a workspace doesn't touch. Look for data in these places:
| Location | Survives workspace delete? | Action |
|---|---|---|
| Unity Catalog tables and volumes | Yes (account-level metastore) | Rebind or reassign the catalog (step 6) |
| External ADLS paths, mounts | Yes (your storage account) | Remove mount references in code |
DBFS root (dbfs:/FileStore, dbfs:/tmp, dbfs:/user) | No | Copy to a UC volume or ADLS |
hive_metastore managed tables in DBFS root | No | Deep clone into Unity Catalog or copy files |
| Workspace files, notebooks, MLflow experiments in the workspace | No | Export (step 4); migrate MLflow runs if needed |
databricks fs ls dbfs:/FileStore -p legacy
databricks fs ls dbfs:/user/hive/warehouse -p legacy
-- Copy a legacy Hive managed table into Unity Catalog before deletion
CREATE TABLE archive.legacy_ws.orders DEEP CLONE hive_metastore.sales.orders;
- DBFS root inventoried; anything needed copied to a volume or ADLS and checked by row or file count
- Hive metastore tables migrated or explicitly signed off as disposable
6. Unity Catalog bindings and ownership
Catalogs bound only to this workspace become unreachable after deletion, but they still exist. Check the bindings:
databricks workspace-bindings get-bindings catalog sales_legacy -p other
Then either bind the catalog to the workspace that takes it over, or schedule it for deletion as a separate, approved change.
-- Objects owned by principals that only exist for this workspace
SELECT table_catalog, table_schema, table_name, table_owner
FROM system.information_schema.tables
WHERE table_owner IN ('legacy-etl-sp', 'legacy-admins');
Move ownership to a long-lived group with ALTER TABLE ... OWNER TO. Do the same for schemas and catalogs.
- Each isolated catalog is either rebound or has a separate delete change
- No Unity Catalog object owned by a principal you are about to remove
7. Identities and credentials
- Service principals used only by this workspace removed from the account (after step 2 shows no callers)
- Personal access tokens and OAuth secrets for those principals revoked; Entra app registrations cleaned up
- Workspace-specific account groups removed or merged
8. Delete the workspace
# Last look: locks and anything unexpected in the managed RG
az lock list -g rg-dbx-legacy -o table
az resource list -g databricks-rg-dbx-legacy-weu-abc123 -o table
az databricks workspace delete -g rg-dbx-legacy -n dbx-legacy-weu --yes
Warning
Remove resource locks only on the workspace resource group, and only after sign-off. Don't try to delete the managed resource group directly. It has a deny assignment, and the workspace delete removes it.
9. Clean up the resources it left behind
These sit outside the managed resource group and keep costing money or holding IPs:
az databricks access-connector list -g rg-dbx-legacy -o table
az network private-endpoint list -g rg-dbx-network -o table # workspace / browser_authentication endpoints
az network vnet subnet list -g rg-dbx-network --vnet-name vnet-dbx -o table
az network private-dns record-set a list -g rg-dns -z privatelink.azuredatabricks.net -o table
- Access connector removed only if no storage credential in Unity Catalog still uses it
- Private endpoints, orphaned DNS A records, NSGs and injected subnets removed or reused
- Diagnostic settings, Log Analytics alerts and budget scopes for the workspace removed
- NCC (serverless network connectivity config) detached if nothing else uses it
Prevent it next time
- Tag every workspace with
owner,cost-centerandexpirywhen you create it, and review expiries every quarter. - Keep data out of the DBFS root from day one. Use Unity Catalog volumes and external locations so a workspace can always be thrown away.
- Run jobs as service principals defined in code, so you can see which identities a workspace depends on.
- Keep this checklist with the evidence queries in your runbook repo, and attach the query output to every decommission ticket.