Databricks Admin · Per-User Configuration

Set a default SQL warehouse per user

The native, no-custom-code path for pinning a Databricks user's SQL queries to a specific warehouse. Honored by the managed /api/2.0/mcp/sql MCP endpoint, the SQL editor, AI/BI dashboards, Genie, alerts, and Catalog Explorer. Three configuration paths: UI, CLI, and REST API.

Audience: Workspace admins, data platform owners, end users Scope: Per-user default warehouse override Verified: Against live Databricks service

01What it does

A per-user default warehouse override tells every Databricks surface that consumes a "default warehouse" to route that user's queries to a specific compute resource — without per-call client configuration.

SQL editor AI/BI dashboards Genie Alerts Catalog Explorer Managed MCP /api/2.0/mcp/sql

Without an override, each surface falls back to the workspace's configured default warehouse (Settings → Compute → Default warehouse), and the managed MCP applies its priority-tier heuristic (any RUNNING warehouse → any STOPPED, serverless first, "shared"-named first, etc.).

With an override, the user gets predictable, deterministic warehouse routing across all these surfaces. The override sits at the workspace level keyed on user identity — admins can set overrides for any user, users can set their own.

02When to use it (and when not to)

This override is the right answer for most warehouse-pinning needs on Databricks. It has one structural limit: it's keyed on user identity, not on workload or agent. If you need different agents owned by the same user to route to different warehouses, you need a custom MCP server instead.

Use per-user override

Native API, no custom code
  • Cost attribution by team or department
  • Compliance audit trails per user
  • Per-team warehouse isolation (one user = one team = one warehouse)
  • Predictable SLA-bound compute
  • Setting defaults for users who don't choose for themselves

Custom MCP server instead

When user-scoped isn't enough
  • One user runs multiple agents that should each route to different warehouses
  • You lack admin access to set overrides for other users
  • The agent should own the warehouse, not the user (shared SP-based agents)
  • You need custom tool behavior beyond execute_sql

For the custom-MCP path, see the main warehouse-pinning guide.

03Configure via the UI

Two surfaces: the workspace-level default warehouse for everyone, and the per-user override that supersedes it for specific users.

A
Workspace-level default warehouse (admin only)
Applies to all users who don't have a per-user override set
  1. Click your username in the top barSettings
  2. In the left sidebar, click Compute
  3. Use the dropdown next to Default warehouse to select your target warehouse
  4. The change applies immediately to SQL editor, AI/BI, Genie, Alerts, Catalog Explorer, and the managed MCP for all un-overridden users
Workspace-default scope

The workspace default is the fallback. Any user with a per-user override (see Path B below) bypasses this setting entirely. To force everyone onto the same warehouse, leave per-user overrides unset or use a script to set them uniformly.

B
Per-user default warehouse override
Users set their own; admins set for any user

As of May 2026, the UI for per-user overrides is documented as available but the exact menu path isn't fully detailed in the public admin docs. Users can typically set their own default via the SQL editor warehouse picker (a "set as my default" affordance appears alongside the warehouse selector). Admins managing other users' overrides should use the CLI or REST API paths below for reliable, scriptable control.

What we know

  1. Users see their effective warehouse in the SQL editor's warehouse picker
  2. The CLI and REST API are the authoritative surfaces for admin-managed overrides
  3. Override changes propagate to all consuming surfaces (SQL editor, MCP, etc.) on the next query
Recommendation

For admin-managed overrides — e.g., setting a team's warehouse for every team member as part of onboarding — use the CLI or REST API. They're scriptable, version-controllable via Terraform, and produce auditable change logs.

04Configure via the Databricks CLI

The Databricks CLI v0.250+ ships five subcommands under databricks warehouses for managing per-user overrides. The CLI is the fastest path for one-off configuration and scriptable rollouts.

Prerequisites

# Install
brew install databricks/tap/databricks

# Authenticate (creates profile in ~/.databrickscfg)
databricks auth login --host https://<your-workspace>.cloud.databricks.com

# Find a warehouse ID
databricks warehouses list --profile <your-profile>

Set your own override

# Create a new CUSTOM override pointing at a specific warehouse
databricks warehouses create-default-warehouse-override \
  me CUSTOM \
  --warehouse-id <warehouse-id> \
  --profile <your-profile>

The me shorthand resolves to your authenticated user. Type CUSTOM means "pin to this specific warehouse"; the alternative LAST_SELECTED uses the most recently selected warehouse instead (sticky behavior, no explicit pin).

Read your current override

databricks warehouses get-default-warehouse-override \
  default-warehouse-overrides/me \
  --profile <your-profile>

# Output:
# {
#   "default_warehouse_override_id": "<numeric-user-id>",
#   "name": "default-warehouse-overrides/<numeric-user-id>",
#   "type": "CUSTOM",
#   "warehouse_id": "<your-warehouse-id>"
# }

Update an existing override

# Change the warehouse target (uses field mask: "*" = update all fields)
databricks warehouses update-default-warehouse-override \
  default-warehouse-overrides/me "*" CUSTOM \
  --warehouse-id <new-warehouse-id> \
  --profile <your-profile>

# Or switch type from CUSTOM to LAST_SELECTED (no warehouse-id needed)
databricks warehouses update-default-warehouse-override \
  default-warehouse-overrides/me "*" LAST_SELECTED \
  --profile <your-profile>

List all overrides (admin only)

databricks warehouses list-default-warehouse-overrides \
  --profile <your-profile>

Set an override for another user (admin only)

# Replace 'me' with the target user's numeric ID
# Get user IDs from: databricks workspace-users list (or SCIM API)
databricks warehouses create-default-warehouse-override \
  <user-id> CUSTOM \
  --warehouse-id <warehouse-id> \
  --profile <admin-profile>

Delete an override

databricks warehouses delete-default-warehouse-override \
  default-warehouse-overrides/me \
  --profile <your-profile>

# After deletion, the user falls back to the workspace-level default warehouse
Idempotent upsert pattern

For scripted rollouts (e.g., setting overrides for every member of a team), use update-default-warehouse-override with the --allow-missing flag. When the override doesn't exist, the flag tells the API to create one instead of failing. This lets you write a single "set the override to X" script that works whether the user has an existing override or not.

05Configure via the REST API

All five operations live under /api/warehouses/v1/default-warehouse-overrides. Same workspace OAuth bearer-token auth as any other Databricks API. The CLI is a thin wrapper around these endpoints.

Endpoint inventory

Method Path Purpose
POST /api/warehouses/v1/default-warehouse-overrides?default_warehouse_override_id=<id> Create override for a user (id can be me or numeric user ID)
GET /api/warehouses/v1/default-warehouse-overrides/<id> Read a single override
PATCH /api/warehouses/v1/default-warehouse-overrides/<id>?update_mask=<mask> Update (use * for all fields)
DELETE /api/warehouses/v1/default-warehouse-overrides/<id> Remove override (fall back to workspace default)
GET /api/warehouses/v1/default-warehouse-overrides List all overrides (admin only)

Example: create a CUSTOM override

POST /api/warehouses/v1/default-warehouse-overrides?default_warehouse_override_id=me
Authorization: Bearer <your-token>
Content-Type: application/json

{
  "type": "CUSTOM",
  "warehouse_id": "<warehouse-id>"
}

Get a bearer token via databricks auth token --host <workspace-url>.

Example: update via PATCH with field mask

PATCH /api/warehouses/v1/default-warehouse-overrides/me?update_mask=*
Authorization: Bearer <your-token>
Content-Type: application/json

{
  "type": "CUSTOM",
  "warehouse_id": "<new-warehouse-id>"
}

The update_mask query parameter follows Google Cloud Resource Manager conventions: * updates all fields, comma-separated field names update only those (e.g., ?update_mask=warehouse_id to change just the target without touching the type).

Example: curl one-liner

HOST=<your-workspace-host>            # e.g. https://abc.cloud.databricks.com
TOKEN=$(databricks auth token --host "$HOST" | jq -r .access_token)
WAREHOUSE_ID=<your-warehouse-id>

curl -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"type\":\"CUSTOM\",\"warehouse_id\":\"$WAREHOUSE_ID\"}" \
  "$HOST/api/warehouses/v1/default-warehouse-overrides?default_warehouse_override_id=me"

Permissions

Operation User permission required
Manage your own overrideAny workspace user
Read another user's overrideWorkspace admin
Set / update / delete another user's overrideWorkspace admin
List all overridesWorkspace admin

The target warehouse must also be accessible to the override's user — i.e., the user needs CAN_USE permission on the warehouse. Setting an override pointing at a warehouse the user can't reach won't fail at create-time, but queries will fail when they try to start.

06Wire the managed MCP into Claude Code or Cursor

After the override is set, you don't need any client-side configuration for warehouse routing — the managed MCP looks up the override server-side on every request. You just need to point your MCP client at the managed endpoint with workspace OAuth. Two paths: a stdio proxy that uses your Databricks CLI authentication (works for both clients), or Cursor's native HTTP + OAuth (Cursor-only).

Managed MCP endpoint

https://<your-workspace-host>/api/2.0/mcp/sql

Note the path ends in /mcp/sql with no warehouse ID. The override is what tells the server where to route — the URL stays the same for every user.

A
Stdio proxy via uv run mcp_proxy.py
Works in Claude Code and Cursor. Uses your ~/.databrickscfg profile for auth.

MCP clients speak stdio (subprocess + stdin/stdout JSON-RPC). The managed MCP endpoint speaks HTTPS with Databricks OAuth. mcp_proxy.py bridges the two — it reads JSON-RPC from stdin, attaches an OAuth bearer token from your CLI profile, and POSTs to the workspace endpoint.

Get the proxy

git clone https://github.com/robkisk/databricks-managed-mcp.git
# The proxy lives at databricks-managed-mcp/mcp_proxy.py
# It uses PEP 723 inline deps — no install step needed

Add to .mcp.json

{
  "mcpServers": {
    "databricks-sql": {
      "command": "uv",
      "args": [
        "run",
        "/absolute/path/to/databricks-managed-mcp/mcp_proxy.py",
        "--path",
        "/api/2.0/mcp/sql",
        "--profile",
        "<your-profile>"
      ]
    }
  }
}

For Claude Code: place this at .mcp.json in your project root, or ~/.claude/.mcp.json globally. For Cursor: .cursor/mcp.json in your project root. Restart the client to load the new server.

B
Cursor-native HTTP + OAuth
Cursor only. No subprocess; uses the editor's built-in OAuth manager.

Cursor supports MCP servers over HTTP with first-class OAuth handling. No proxy script needed — Cursor opens a browser tab for the workspace login on first use and caches the token.

Add to .cursor/mcp.json

{
  "mcpServers": {
    "databricks-sql": {
      "type": "http",
      "url": "https://<your-workspace-host>/api/2.0/mcp/sql",
      "oauth": {
        "clientId": "<databricks-oauth-app-client-id>",
        "callbackPort": 8080
      }
    }
  }
}

The clientId is a Databricks OAuth app client ID — a workspace admin creates this once via databricks account custom-app-integration create (account-level call, requires Account Admin) and shares it with users in the workspace. Hardcode the actual UUID value; placeholder strings like $DATABRICKS_OAUTH_CLIENT_ID are not substituted at runtime.

Test the wired client

After restarting your MCP client, ask the agent a quick SQL question:

"Use the databricks-sql MCP to run: SELECT current_user(), now()"

If the override is wired correctly, the query lands on your override warehouse. Verify by checking warehouse state on the Databricks control plane — see Verify it works below for the full state-delta methodology.

Per-user, not per-client

Both clients use the same managed MCP endpoint, and the override applies to the calling user. Wiring Claude Code and Cursor for the same user means both route to the override warehouse — there is no way to send Claude Code queries to one warehouse and Cursor queries to another while sharing a user. If you need that split, use a custom MCP server (see the main pinning guide).

07Verify it works

Three layers of verification — each tighter than the last. Use whichever fits your confidence requirement.

Layer 1 — confirm the override is recorded

databricks warehouses get-default-warehouse-override \
  default-warehouse-overrides/me \
  --profile <your-profile>

Returns the override's type and warehouse_id. If warehouse_id matches your intended target, the override is stored correctly.

Layer 2 — confirm the algorithm picks it

databricks experimental aitools tools get-default-warehouse --profile <your-profile>

This CLI command resolves the same default-warehouse lookup that the managed MCP uses. The returned warehouse ID should match your override target. If it doesn't, the override is recorded but not winning the priority lookup — file a support ticket with both values.

Layer 3 — observe the routing end-to-end

Stop your target warehouse and every other warehouse the lookup might reach. Send a query through the managed MCP (or any consuming surface). The target warehouse should transition STOPPED → RUNNING, and no other warehouse should be touched.

# Stop all warehouses to baseline
for WID in $(databricks warehouses list --profile <p> -o json | jq -r '.[].id'); do
  databricks warehouses stop "$WID" --profile <p> &
done; wait

# Send a query through any default-warehouse-using surface (MCP, SQL editor, etc.)
# Then re-list warehouses and check which one woke up:
databricks warehouses list --profile <p> -o json | jq '.[] | {id, state, name}'
Why state-delta verification

Layer 1 confirms persistence, Layer 2 confirms the resolver, Layer 3 confirms the consuming surface honors what the resolver returns. State-delta verification (Layer 3) is robust because warehouse state transitions are observable on the Databricks control plane and can't be faked by a misbehaving downstream component.

08Reference

Override types

TypeBehaviorUse when
CUSTOM Pin to the specific warehouse_id field You want explicit, predictable routing — admin-managed or user-set with intent
LAST_SELECTED Use whichever warehouse the user most recently chose You want sticky behavior — user's last UI selection persists across sessions

Scoping rules

Terraform support

Databricks ships a Terraform data source databricks_warehouses_default_warehouse_override for reading existing overrides. As of May 2026 the corresponding resource for declarative creation isn't shipped in the provider — use the CLI or REST API for now. Track the Terraform provider changelog for resource availability.

Related Databricks documentation