Home / Databricks on Azure

Databricks on AzureTroubleshootingBeginner

Azure Databricks costs missing tags in Azure Cost Management - cluster, pool, workspace and serverless tag propagation

Databricks spend shows as untagged in Azure cost analysis or chargeback reports. Find which tag path failed (pool, workspace, conflict, restart, serverless) and fix it.

Deepak Bhardwaj7 min read

Applies toAzure Databricks (classic all-purpose and jobs compute, instance pools, SQL warehouses, serverless usage policies), Azure Cost Management, system.billing.usage

Symptoms

  • In Azure cost analysis, grouping by your costcenter or team tag shows a large untagged bucket for the Databricks managed resource group.
  • A cluster has the right custom tags in the Databricks UI, but its VMs and disks in Azure don't.
  • A tag you added to the workspace last week still isn't on running clusters.
  • Serverless notebooks, jobs or pipelines don't appear in Azure cost analysis by tag at all.
  • A cluster or pool fails to start with an invalid settings error after a compute policy change.

How Databricks tags reach Azure

Source of the tag Where it lands
Default tags (Vendor, ClusterId, ClusterName, Creator, plus JobId and RunName on job compute) Azure VMs and the Databricks usage records
Workspace tags (set on the Azure resource) Aggregated onto the VMs for every cluster and pool in the workspace
Cluster custom tags Cluster VMs, unless the cluster runs on a pool
Pool custom tags VMs created by the pool
SQL warehouse custom tags Warehouse usage records and its classic compute
Serverless usage policy tags system.billing.usage only. Serverless runs in the Databricks account, so there are no VMs in your subscription to tag

The VM charges in your subscription carry the tags on the VMs. DBU charges are a separate meter. Look at a DBU line in your cost export to see which tags it carries before you build a chargeback report on it. For DBUs, system.billing.usage is the source to trust.

Quick diagnosis

Symptom Likely cause Fix
Cluster tags missing on VMs, cluster uses a pool Pool clusters only get workspace and pool tags Put the tags on the pool, or use one pool per cost owner
New workspace tag not on clusters Workspace tags take up to an hour to sync and don't apply to running compute Wait, then edit and restart the compute, or let the pool expand
Edited cluster tags not on VMs Tag changes apply after a restart Restart the cluster
Tag appears as x_vendor, x_creator Custom tag key clashes with a default tag Rename the custom tag
Cluster or pool won't start after a policy change The policy adds a tag that conflicts with a default tag or a pool tag Remove the conflicting key from the policy
Some tags missing on a heavily tagged VM More than 50 tags after aggregation; extra tags are dropped Cut the number of workspace, pool and cluster tags
Tag rejected Characters outside letters, numbers, spaces and + - = . _ : / @ Use allowed characters only
Serverless spend untagged No serverless usage policy assigned Create and assign a usage policy (Public Preview)

Checks

1. Is the cluster on a pool?

databricks clusters get 0612-091522-abcd1234 --output json \
  | jq '{name: .cluster_name, pool: .instance_pool_id, driver_pool: .driver_instance_pool_id, tags: .custom_tags}'

If pool or driver_pool has a value, the cluster's custom_tags never reach the VMs. Check the pool instead:

databricks instance-pools get 0612-085511-pool42 --output json | jq '.custom_tags'

2. What tags do the VMs actually have?

Find the managed resource group and list VM tags:

MRG_ID=$(az databricks workspace show -g rg-data-prod -n dbw-data-prod \
  --query managedResourceGroupId -o tsv)
MRG=${MRG_ID##*/}

az vm list -g "$MRG" --query "[].{vm:name, cluster:tags.ClusterName, costcenter:tags.costcenter, pool:tags.DatabricksInstancePoolId}" -o table

VMs with a pool value and no costcenter confirm the pool problem. VMs with no costcenter and no pool mean the cluster wasn't tagged or hasn't been restarted since tagging.

3. What tags does the workspace have?

az databricks workspace show -g rg-data-prod -n dbw-data-prod --query tags

Add or change workspace tags with a merge, so existing tags stay:

WS_ID=$(az databricks workspace show -g rg-data-prod -n dbw-data-prod --query id -o tsv)
az tag update --resource-id "$WS_ID" --operation Merge --tags costcenter=CC1234 env=prod

Warning

Don't try to tag the managed resource group or its resources directly. Databricks manages them, they are protected by a deny assignment, and Databricks sets VM tags at launch. Tag the workspace, pools and clusters instead.

4. How much DBU spend is untagged?

Use the billing system table, which covers classic and serverless:

SELECT
  billing_origin_product,
  usage_metadata.cluster_id   AS cluster_id,
  usage_metadata.job_id       AS job_id,
  usage_metadata.warehouse_id AS warehouse_id,
  identity_metadata.run_as    AS run_as,
  SUM(usage_quantity)         AS dbus
FROM system.billing.usage
WHERE usage_date >= current_date() - INTERVAL 30 DAYS
  AND custom_tags['costcenter'] IS NULL
GROUP BY ALL
ORDER BY dbus DESC
LIMIT 50;

Fix the top rows first: usually a few shared all-purpose clusters, pools or untagged serverless jobs account for most of it.

Fixes

Tag pools, not just clusters

If teams share a pool, cluster tags are lost on the VMs. Create one pool per cost owner, or accept pool-level allocation:

databricks instance-pools edit --json '{
  "instance_pool_id": "0612-085511-pool42",
  "instance_pool_name": "pool-finance-ds4",
  "node_type_id": "Standard_D4ds_v5",
  "custom_tags": {"costcenter": "CC1234", "team": "finance"}
}'

The edit call takes the full pool definition. Copy the current settings from instance-pools get first so you don't reset the idle and size limits. Existing idle instances keep their old tags, and new tags apply as the pool expands.

Enforce tags with compute policies

Make the tag required and limited to known values:

{
  "custom_tags.costcenter": { "type": "allowlist", "values": ["CC1234", "CC2001", "CC3005"] },
  "custom_tags.team":       { "type": "unlimited", "isOptional": false }
}

Apply it to the policy used by each team's clusters, then restart running clusters so the tags reach the VMs.

Caution

Never add a policy tag whose key matches a default tag (Vendor, Creator, ClusterName, ClusterId, JobId, RunName) or a pool tag. Clusters under that policy fail to start, including production jobs.

Tag serverless with usage policies

Serverless usage policies (Public Preview, formerly called budget policies) tag serverless notebooks, jobs, pipelines and model serving endpoints. Create a policy per team in the workspace settings, add the custom tags and assign users or groups. Those tags then show up in system.billing.usage.custom_tags, not in Azure cost analysis.

Fill gaps in Azure reports

For the Azure side, turn on tag inheritance in Cost Management settings. It applies subscription and resource group tags to usage records, so untagged Databricks VM costs at least pick up the subscription's cost center. It is a reporting change and doesn't modify resource tags.

Prevent it next time

  • Treat workspace tags as the baseline (costcenter, env, owner), and use pool and cluster tags only for finer splits.
  • Require tags through compute policies for classic compute and usage policies for serverless.
  • Schedule the untagged-DBU query weekly as a SQL alert to the FinOps channel.
  • Build chargeback from system.billing.usage joined to system.billing.list_prices for DBUs, and from Azure cost exports for VMs, disks and networking. Don't expect one source to cover both.
  • Keep the total tag count per resource well under 50 after aggregation.