Workspaces
Mental Model
A workspace is the compute entry point.
It cannot change region or merge with another after creation, so the layout is a one-way decision.
Databricks manages workspaces through Terraform, not the console wizard.
databricks-platform-provisioning writes that Terraform from the requirements and runs plan, then stops for a human approval before apply.
Default to three workspaces (dev, staging, prod).
One workspace is fine for a POC.
Two topologies:
| Topology | Network | When to use |
|---|---|---|
| Serverless | No customer VPC/VNet. AWS compute_mode=SERVERLESS. Azure computeMode=Serverless. |
POC and teams that do not need classic compute plane networking. |
| Classic | Dedicated customer VPC/VNet plus Secure Cluster Connectivity. Also supports serverless compute inside the workspace. | Production, Private Link, or classic clusters required. |
Goal
One workspace per environment in the chosen topology, plus a Unity Catalog metastore in the region (create or attach).
Prerequisites
- Pre-requisites passing, including
terraform versionat 1.9.0 or later. - Auth surface: account (plus cloud CLI for the target cloud).
- An authenticated cloud CLI session with permission to create IAM roles, object storage, and (classic only) VPC or VNet resources.
- A Databricks account-admin principal: OAuth SP on AWS,
azure-clion Azure with matching tenant (below), or service account impersonation on GCP.
Skill
databricks-platform-provisioning (ai-platform-kit).
Read its SKILL.md, then the file for the target cloud only.
Reading the other clouds' files adds noise.
For AWS serverless, use the skill's serverless / no-customer-VPC path (field scenario aws-serverless-ncc), not a BYOVPC template.
For Azure serverless, azurerm may not expose computeMode=Serverless yet.
Use az databricks workspace create --compute-mode Serverless (or azapi) until the skill documents a Terraform path.
Classic Azure uses VNet injection templates.
Inputs
Ask for every human-sourced value in one message.
| Input | Source | How to obtain |
|---|---|---|
| Cloud | Human | aws, azure, or gcp |
| Cloud region | Human | Must support the chosen topology. Check feature-region-support for Serverless workspaces when topology is serverless. |
| Topology | Human | serverless or classic (table above) |
| Databricks account ID | Human | Account console, top-right user menu |
| Environment strategy | Human | One workspace, or dev / staging / prod |
| Purpose | Human | POC or production |
| Existing network? | Human | Classic only: new network, or an existing one (VPC/VNet ID, two private subnets in different AZs when the region has AZs, security group IDs). Omit zones on PIP/NAT in non-zonal regions (example: Azure westcentralus). |
| Naming convention | Human | Chosen from the ≤3 options in Run step "Naming" before any HCL is written. Maps to resource prefix, workspace names, and related cloud names. |
| Resource prefix | You derive | From the chosen naming convention. Object storage names are globally unique, so never reuse a prefix. |
| Workspace names | You derive | From the chosen naming convention. Examples: <prefix>-dev, dev-<prefix>, or a human label like development. |
Do not invent a fourth naming scheme in the same turn. If the human already has an org standard, make that option 1 and offer at most two alternates.
Per-cloud provider auth:
| Cloud | Databricks provider auth | What you need |
|---|---|---|
| AWS | OAuth M2M with an account-admin service principal | SP client ID and OAuth secret. The secret is shown once at generation. |
| Azure | auth_type = "azure-cli" on every provider block |
az login --tenant <account-tenant>, azure_tenant_id on every provider block, and a subscription in that same tenant with Contributor (classic also needs networking rights). |
| GCP | auth_type = "google-id" with service account impersonation |
The service account, with impersonation rights. |
Run
0. Auth precheck
Refuse if the human did not name all of these: Databricks account id, Databricks account CLI profile, target cloud (aws, azure, or gcp), cloud account id, cloud CLI profile.
Do not invoke the skill until every named target is present.
Run live checks:
databricks auth profiles
databricks account workspaces list --profile <account-profile> -o json | jq 'length'
aws sts get-caller-identity --profile <aws-profile> # AWS: Account must equal named cloud account id
az account show --profile <azure-profile> # Azure: tenant + subscription must match named ids
gcloud auth list # GCP: active account must match named project
Compare the live cloud identity to the human-named cloud account id. When the account API returns an account id, compare it to the human-named Databricks account id.
On any failure, print blocked: auth preflight failed, name the failing check, give the human these remediations, and stop. Do not invoke the skill. Do not run Terraform.
| Check failed | Human must run |
|---|---|
Account profile missing or Valid=NO |
databricks auth login --host <account-host> --profile <account-profile> or fix M2M SP secret and Account admin role |
account workspaces list fails |
Confirm Account admin on the SP; regenerate OAuth secret (AWS) |
| Cloud CLI not authenticated | aws sso login --profile <aws-profile> / az login --tenant <tenant> / gcloud auth login |
| Cloud account id mismatch | Pick the profile whose account id matches the human-named cloud account id |
| Databricks account id mismatch | Fix the account profile or the human-named account id before continuing |
1. Pre-flight
aws sts get-caller-identity --profile <aws-profile> # AWS
az account show # Azure: confirm tenant + subscription
gcloud auth list # GCP
env | grep -i DATABRICKS # stale DATABRICKS_HOST or DATABRICKS_TOKEN breaks provider auth
databricks auth profiles # never echoes secrets
terraform version # >= 1.9.0
A stale DATABRICKS_HOST or DATABRICKS_TOKEN in the shell is the most common cause of a confusing provider auth failure.
Unset them.
Prefer one-shot env VAR=... cmd over exporting SP secrets into the shell for the rest of the session.
Azure only: confirm az group create would succeed on the target subscription (Contributor or equivalent).
Do not trust a precheck OK that only reflects view-only policy.
2. Naming (mandatory before HCL)
Organizations disagree on Databricks vs cloud names. Workspace name, resource prefix, root bucket, and IAM name stems are different strings that must stay consistent inside one Terraform apply.
Present at most three options in one message. Wait for an explicit pick. Then map the pick to skill/Terraform inputs. Do not fill templates before the pick.
Example options (adapt labels to the customer; keep ≤3):
| Option | Workspace name pattern | Resource prefix | Notes |
|---|---|---|---|
| A | <prefix>-dev (example asjawsrv-dev) |
asjawsrv |
Common skill default: env as suffix. |
| B | dev-<prefix> (example dev-asjawsrv) |
asjawsrv |
Env as prefix. |
| C | Exact human label (example development) |
short unique stem for cloud resources | Workspace display name decoupled from cloud prefix. |
Multi-env: apply the same pattern to staging/prod (<prefix>-staging / staging-<prefix> / human labels).
Cloud object names (root storage, credentials) still need a globally unique stem derived from the chosen prefix.
State that stem in the option table.
3. Permission sweep
Read-only. Returns which deployment topologies the caller's cloud permissions support, before any HCL exists.
bash precheck-aws.sh # or precheck-azure.sh / precheck-gcp.sh, from the skill's scripts/
4. Invoke the skill
Hand the skill the collected inputs, including topology and the chosen naming mapping, and let it run its own intake for anything missing.
It writes the HCL, then runs terraform init and terraform plan.
5. Plan review
The skill stops here.
Show the plan to the user and get an explicit approval before terraform apply.
Resources created here cost money and are slow to unwind.
If the human already approved apply in the task brief, run terraform apply and record that approval.
Do not treat plan as done.
Verify
Match the environment strategy.
# Workspaces RUNNING (filter by prefix)
databricks account workspaces list --profile <account-profile> -o json \
| jq -r '.[] | select(.workspace_name | startswith("<prefix>")) | "\(.workspace_name)\t\(.workspace_status)"'
Expected: one RUNNING line for a POC, or three for dev/staging/prod.
Azure fallback when account list cannot see the workspace (auth gap): az databricks workspace show for provisioningState and computeMode, then a workspace-profile databricks current-user me.
# Metastores in the region. default_data_access_config_id may be null when the template creates a metastore without a storage root; catalog storage is handled on Catalogs.
databricks account metastores list --profile <account-profile> -o json \
| jq '.[] | select(.region=="<region>") | {name, metastore_id, owner, default_data_access_config_id}'
If more than one metastore returns: do not auto-pick.
Prefer an account-standard metastore (often owner account users or a shared naming convention).
Never attach to a user-named orphan without approval.
In shared sandboxes, creating <prefix>-metastore is valid when the human wants isolation.
One usable metastore per region is the hard limit for attach; creating another when one already exists may fail.
# Workspace-level auth. M2M profiles return the SP application id, not a human email.
databricks current-user me --profile <workspace-profile> -o json | jq -r '.userName'
Compute verification after the workspace is up:
- Serverless topology: serverless SQL warehouse path only (CREATE/INSERT/SELECT/DROP on a UC table once catalogs exist). Skip classic clusters.
- Classic topology: classic cluster and serverless SQL as in
databricks-deployment-verification. Start the classic cluster early; cold start is 10 to 15 minutes.
On Azure, workspace admin for the creator is often automatic via Azure AD. databricks_mws_permission_assignment does not work on Azure; do not use it there.
Where this fails
| Symptom | Cause | Fix |
|---|---|---|
| blocked: auth preflight failed before Run | Missing named account id, account profile, cloud account id, or cloud profile | Ask the human for every required target; rerun ### 0 |
Account profile Valid=NO or account list fails |
Expired login or wrong SP secret | databricks auth login --host <account-host> --profile <account-profile> or fix M2M and Account admin role |
Cloud STS / az account show fails or account id mismatch |
Wrong or expired cloud profile | aws sso login --profile <aws-profile> / az login --tenant <tenant> / gcloud auth login; pick the profile that matches the named cloud account id |
| Skill invoked despite red precheck | Agent skipped ### 0 | Always run ### 0 first; stop on any failure |
400 BAD_REQUEST: Failed to get oauth access token (AWS) |
SP is not an account admin, or the secret is wrong | Confirm the Account admin role on the Roles tab, regenerate the secret |
| Provider hits the wrong host | DATABRICKS_HOST or DATABRICKS_TOKEN set in the shell |
unset both, re-run |
PERMISSION_DENIED: User is not an owner of Metastore |
The SP cannot create catalogs | Add the SP to the metastore admin group |
| Apply fails on IAM or VPC | Cloud principal lacks create rights | Run the precheck script and report the gaps rather than retrying |
| Multiple metastores returned for the region | Orphan metastores from earlier deploys | Report the list; use the decision rules under Verify |
Azure IncorrectClaimException |
az tenant ≠ Databricks account tenant |
az login --tenant <account-tenant> and pick a subscription in that tenant |
| Azure workspace missing from account list | Created under the wrong tenant/subscription | Recreate in the account's tenant, or obtain account admin on the account that owns the workspace |
| Azure zonal PIP/NAT fails | Region has no availability zones | Omit zones on Public IP / NAT |
Precheck OK but resourcegroups/write denied |
View-only subscription | Switch to a subscription with Contributor (and later UAA for UC storage) |
| Workspace or bucket names surprise the human | Naming step skipped; skill default assumed | Re-run Naming (≤3 options) and map the pick before plan |
Next
- Do next: Catalogs
- Manual fallback: Starter Journey: create workspaces