Provisions what Databricks' product UI calls a "SQL Warehouse" (serverless or classic) β implemented via the Terraform resource
databricks_sql_endpoint, against providerdatabricks/databricks~> 1.117.0.databricks_sql_warehousedoes not exist in this or any provider version; see "Schema notes that bite" below before you go looking for it.
- π·οΈ Wraps
databricks_sql_endpointβ Databricks' Terraform-level name for what its product UI calls a SQL Warehouse. There is nodatabricks_sql_warehouseresource to find in this provider. - π₯οΈ Creates one SQL warehouse, serverless or classic, sized via
cluster_size. - π Defaults to
auto_stop_mins = 10β this library's house secure default, overriding the Databricks API's own more permissive default, so idle compute doesn't bill indefinitely. - π·οΈ Accepts cost-attribution tags as a plain
map(string)(var.custom_tags) and remaps them into the resource's real nestedtags { custom_tags {... } }block shape internally. - π« Never accepts a credential, host, or account ID.
- π Workspace-plane only β this resource cannot be used with an account-level provider.
π‘ Why it matters: a SQL warehouse is billed compute the moment it's running. The auto-stop default in this module is the single highest-leverage cost control a caller can leave untouched.
If these Terraform modules have been helpful to you or your organization, I'd appreciate your support in any of the following ways:
- β Star this repository to help others discover this Terraform module.
- π€ Connect with me on LinkedIn: linkedin.com/in/microsoftexpert
- β Buy me a coffee: buymeacoffee.com/microsoftexpert
Whether it's a star, a professional connection, or a coffee, every gesture helps keep these modules actively maintained and continually improving. Thank you for being part of the community!
flowchart LR
THIS["tf-mod-databricks-sql-warehouse"]
style THIS fill:#FF3621,color:#fff,stroke:#1B3139,stroke-width:1px
SQLQUERY["tf-mod-databricks-sql-query"]
style SQLQUERY fill:#1B3139,color:#fff,stroke:#1B3139,stroke-width:1px
PERMISSIONS["tf-mod-databricks-permissions"]
style PERMISSIONS fill:#F2F2F2,color:#1B3139,stroke:#CCCCCC,stroke-width:1px
THIS -->|"id becomes warehouse_id"| SQLQUERY
THIS -->|"id becomes object_id for a CAN_USE grant"| PERMISSIONS
tf-mod-databricks-sql-query is this module's nearest sibling β its warehouse_id input consumes
this module's id output directly. tf-mod-databricks-permissions is a light-neutral sibling that
can attach workspace-object ACLs (CAN_USE, CAN_MANAGE) to this warehouse by its id.
βΉοΈ
tf-mod-databricks-sql-queryis a seeded module name in this same catalog batch and has not yet been authored as of this README β the end-to-end composition example in the Example Library below reflects its planned contract, not a verified cross-moduleterraform plan.
flowchart TB
subgraph INPUTS["var.*"]
CORE["name / cluster_size"]
SIZE["auto_stop_mins / enable_serverless_compute / enable_photon"]
SCALE["min_num_clusters / max_num_clusters / spot_instance_policy / warehouse_type"]
MISC["instance_profile_arn / no_wait / custom_tags / channel"]
end
KEYSTONE["databricks_sql_endpoint.this"]
style KEYSTONE fill:#1B3139,color:#fff,stroke:#1B3139,stroke-width:1px
subgraph OUTPUTS["outputs"]
ID["id / name"]
JDBC["jdbc_url"]
end
CORE --> KEYSTONE
SIZE --> KEYSTONE
SCALE --> KEYSTONE
MISC --> KEYSTONE
KEYSTONE --> ID
KEYSTONE --> JDBC
Resource inventory: one resource, databricks_sql_endpoint.this. No child collection.
| Requirement | Value |
|---|---|
| Terraform | >= 1.12.0 |
databricks/databricks |
~> 1.117.0 |
| Provider block | None β the caller's root module configures provider "databricks" {} |
tags / custom_tags |
Supported, but as a nested block β see below, not a passthrough map |
timeouts |
Supported by this resource's schema; not exposed as a v1.0.0 variable (no caller need identified yet) |
Schema notes that bite:
- The resource is
databricks_sql_endpoint, notdatabricks_sql_warehouse. Databricks renamed the product-facing term to "SQL Warehouse" without renaming the underlying Terraform resource β the resource remainsdatabricks_sql_endpointas of provider~> 1.117.0. Do not add adatabricks_sql_warehouseresource block; it does not exist andterraform validatewill fail with an unsupported resource type error if you do. tagsis a nested block, not a plainmap(string). The live schema models it astags { custom_tags { key = string, value = string } }(tagsitself,nesting_mode = "list",max_items = 1;custom_tagsunbounded within it, bothkey/valuerequired strings) β a genuinely different shape fromdatabricks_job/databricks_pipeline, whosetagsargument is a flatmap(string). This module'svar.custom_tagsis amap(string)at the variable-schema level for caller ergonomics;main.tfremaps it into the nested-block shape viadynamic "tags"wrapping adynamic "custom_tags". A caller never authors the raw block shape.nameandcluster_sizeare both schema-Required β there is no platform default for either; every call must supply both explicitly.data_source_id,jdbc_url,odbc_params,state,health,creator_name,num_active_sessions, andnum_clustersare computed-only; none are settable inputs.instance_profile_arnis AWS-specific resource configuration metadata (not module authentication) β leave it null on Azure/GCP workspaces.
- Workspace-level SQL warehouse creation entitlement (workspace admin, or a user/group explicitly
granted warehouse-creation permission by a workspace admin). This entitlement model is not
enumerated as an argument in the machine-readable schema (
schema.jsoncarries no IAM metadata) β flagging this as house-standard guidance grounded in Databricks' documented entitlement model, not a schema-verified fact. - If
instance_profile_arnis set: the applying identity must be permitted to attach that AWS instance profile.
- Workspace-level provider context (not account-level) β
databricks_sql_endpointis a workspace-plane resource. - If
enable_serverless_compute = true, serverless SQL compute must already be enabled for the workspace by a workspace/account admin; this module cannot enable that feature flag itself. - If
instance_profile_arnis set, the referenced AWS instance profile must already exist and be registered with the workspace.
tf-mod-databricks-sql-warehouse/
βββ providers.tf # required_providers only β no provider {} block
βββ variables.tf # name, cluster_size (both required), auto_stop_mins (default 10),...
βββ main.tf # databricks_sql_endpoint.this
βββ outputs.tf # id first, then name, then jdbc_url
βββ SCOPE.md # cross-module contract
βββ README.md # this file
βββ examples/
βββ basic/
βββ main.tf # smallest real, runnable call
module "adhoc_warehouse" {
source = "git::https://github.com/microsoftexpert/tf-mod-databricks-sql-warehouse.git?ref=v1.0.0"
name = "analytics-adhoc"
cluster_size = "2X-Small"
enable_serverless_compute = true
# auto_stop_mins left at the module's secure default (10 minutes)
}The caller's root module configures provider "databricks" {} (host + auth) and passes it in
implicitly, or explicitly via a providers = {} map β this module accepts neither.
Consumes: none β this is a standalone module with no cross-module inputs beyond optional
resource-metadata fields (instance_profile_arn) that reference externally-managed AWS objects,
not another module's output.
Emits:
| Output | Description | Consumed by |
|---|---|---|
id |
ID of the databricks_sql_endpoint resource |
tf-mod-databricks-sql-query (warehouse_id input), tf-mod-databricks-permissions (object ID for a grant) |
name |
Display name of the warehouse | Auditing / drift-detection tooling |
jdbc_url |
JDBC connection URL (non-sensitive β a connection endpoint, not a credential) | BI tool / client connection configuration |
1 Β· Minimal serverless warehouse (secure default left in place)
module "adhoc_warehouse" {
source = "git::https://github.com/microsoftexpert/tf-mod-databricks-sql-warehouse.git?ref=v1.0.0"
name = "analytics-adhoc"
cluster_size = "2X-Small"
enable_serverless_compute = true
}π‘
auto_stop_minsis omitted here, so it takes the module's house default of10β not the Databricks API's own more permissive default.
2 Β· Always-on warehouse (auto-stop disabled)
module "always_on_warehouse" {
source = "git::https://github.com/microsoftexpert/tf-mod-databricks-sql-warehouse.git?ref=v1.0.0"
name = "bi-dashboards-prod"
cluster_size = "Medium"
auto_stop_mins = 0
}
β οΈ auto_stop_mins = 0leaves this warehouse's compute running indefinitely and billing continuously. Only set this for a warehouse serving latency-sensitive production BI traffic where cold-start time is unacceptable, and treat it as a deliberate, reviewed cost decision.
3 Β· Classic (non-serverless) cluster-size example
module "classic_warehouse" {
source = "git::https://github.com/microsoftexpert/tf-mod-databricks-sql-warehouse.git?ref=v1.0.0"
name = "legacy-classic"
cluster_size = "Small"
enable_serverless_compute = false
warehouse_type = "CLASSIC"
}4 Β· Min/max multi-cluster autoscaling
module "concurrent_bi_warehouse" {
source = "git::https://github.com/microsoftexpert/tf-mod-databricks-sql-warehouse.git?ref=v1.0.0"
name = "bi-concurrent"
cluster_size = "Large"
min_num_clusters = 1
max_num_clusters = 4
}βΉοΈ Multi-cluster autoscaling lets the warehouse add clusters under concurrent query load rather than queueing β relevant mainly for classic compute; serverless scales differently under the hood.
5 Β· Photon-enabled warehouse
module "photon_warehouse" {
source = "git::https://github.com/microsoftexpert/tf-mod-databricks-sql-warehouse.git?ref=v1.0.0"
name = "analytics-photon"
cluster_size = "Medium"
enable_photon = true
}6 Β· Spot-instance cost-optimized policy (classic compute)
module "cost_optimized_warehouse" {
source = "git::https://github.com/microsoftexpert/tf-mod-databricks-sql-warehouse.git?ref=v1.0.0"
name = "batch-sql-cost-optimized"
cluster_size = "Small"
enable_serverless_compute = false
spot_instance_policy = "COST_OPTIMIZED"
}βΉοΈ
spot_instance_policyonly affects classic (non-serverless) compute β Databricks manages serverless compute's underlying infrastructure directly.
7 Β· Reliability-optimized spot policy
module "reliability_warehouse" {
source = "git::https://github.com/microsoftexpert/tf-mod-databricks-sql-warehouse.git?ref=v1.0.0"
name = "prod-sql-reliable"
cluster_size = "Large"
enable_serverless_compute = false
spot_instance_policy = "RELIABILITY_OPTIMIZED"
}8 Β· Release channel pinned to PREVIEW
module "preview_channel_warehouse" {
source = "git::https://github.com/microsoftexpert/tf-mod-databricks-sql-warehouse.git?ref=v1.0.0"
name = "dbsql-preview-testing"
cluster_size = "X-Small"
channel = {
name = "CHANNEL_NAME_PREVIEW"
}
}βΉοΈ Use the
PREVIEWchannel only in a non-production warehouse used to validate upcoming DBSQL runtime changes before they reachCURRENT.
9 Β· Custom tags for cost attribution
module "tagged_warehouse" {
source = "git::https://github.com/microsoftexpert/tf-mod-databricks-sql-warehouse.git?ref=v1.0.0"
name = "finance-reporting"
cluster_size = "Small"
custom_tags = {
cost_center = "finance"
environment = "prod"
owner = "data-platform-team"
}
}π‘
var.custom_tagsis a plain map here β this module remaps it into the resource's realtags { custom_tags { key, value } }nested-block shape internally. See "Schema notes that bite."
10 Β· AWS instance-profile-attached warehouse
module "s3_access_warehouse" {
source = "git::https://github.com/microsoftexpert/tf-mod-databricks-sql-warehouse.git?ref=v1.0.0"
name = "s3-external-tables"
cluster_size = "Medium"
enable_serverless_compute = false
instance_profile_arn = "arn:aws:iam::123456789012:instance-profile/databricks-sql-s3-reader"
}βΉοΈ AWS-only. Leave
instance_profile_arnnull on Azure/GCP workspaces.
11 Β· no_wait for faster apply cycles
module "fast_apply_warehouse" {
source = "git::https://github.com/microsoftexpert/tf-mod-databricks-sql-warehouse.git?ref=v1.0.0"
name = "dev-sandbox"
cluster_size = "2X-Small"
no_wait = true
}βΉοΈ
no_wait = truereturns control to Terraform once the API call is accepted, without waiting for the warehouse to reach a running state β useful in fast dev-loop applies, less useful when a caller needs the warehouse actually running before the next resource applies.
12 Β· Minimal least-privilege, lowest-cost baseline (recommended starting point)
module "baseline_warehouse" {
source = "git::https://github.com/microsoftexpert/tf-mod-databricks-sql-warehouse.git?ref=v1.0.0"
name = "baseline-adhoc"
cluster_size = "2X-Small"
# auto_stop_mins left at the secure default: 10
}13 Β· Multiple team warehouses via for_each at the caller level
locals {
team_warehouses = {
finance = "2X-Small"
ml = "Small"
bi = "Medium"
}
}
module "team_warehouses" {
for_each = local.team_warehouses
source = "git::https://github.com/microsoftexpert/tf-mod-databricks-sql-warehouse.git?ref=v1.0.0"
name = "${each.key}-adhoc"
cluster_size = each.value
enable_serverless_compute = true
}βΉοΈ
for_eachis applied at the caller's root-module level β this module itself has no child collection to iterate; each instance creates exactly one warehouse.
ποΈ 14 Β· End-to-end composition β warehouse β query
module "analytics_warehouse" {
source = "git::https://github.com/microsoftexpert/tf-mod-databricks-sql-warehouse.git?ref=v1.0.0"
name = "analytics-adhoc"
cluster_size = "Small"
enable_serverless_compute = true
}
module "daily_active_users_query" {
source = "git::https://github.com/microsoftexpert/tf-mod-databricks-sql-query.git?ref=v1.0.0"
display_name = "Daily Active Users"
warehouse_id = module.analytics_warehouse.id
query_text = "SELECT event_date, COUNT(DISTINCT user_id) AS dau FROM analytics.events GROUP BY event_date"
}βΉοΈ
tf-mod-databricks-sql-queryhas not yet been authored as of this README β this composition reflects its planned contract (per this library's catalog and recommended authoring order), not yet a verified cross-moduleterraform plan.
| Variable | Type | Default | Notes |
|---|---|---|---|
name |
string |
β (required) | |
cluster_size |
string |
β (required) | Closed T-shirt-size enum |
auto_stop_mins |
number |
10 |
Secure default; 0 = always-on, |
enable_serverless_compute |
bool |
null |
Requires workspace serverless entitlement |
enable_photon |
bool |
null |
|
min_num_clusters |
number |
null |
|
max_num_clusters |
number |
null |
|
spot_instance_policy |
string |
null |
COST_OPTIMIZED | RELIABILITY_OPTIMIZED |
warehouse_type |
string |
null |
PRO | CLASSIC |
instance_profile_arn |
string |
null |
AWS-only |
no_wait |
bool |
null |
|
custom_tags |
map(string) |
{} |
Remapped into nested tags { custom_tags {... } } |
channel |
object({ name, dbsql_version }) |
null |
Both fields optional strings |
Full variable declarations
variable "name" {
type = string
}
variable "cluster_size" {
type = string
# validation: one of 2X-Small, X-Small, Small, Medium, Large, X-Large, 2X-Large, 3X-Large, 4X-Large
}
variable "auto_stop_mins" {
type = number
default = 10
# validation: >= 0
}
variable "enable_serverless_compute" {
type = bool
default = null
}
variable "enable_photon" {
type = bool
default = null
}
variable "min_num_clusters" {
type = number
default = null
}
variable "max_num_clusters" {
type = number
default = null
}
variable "spot_instance_policy" {
type = string
default = null
# validation: COST_OPTIMIZED | RELIABILITY_OPTIMIZED
}
variable "warehouse_type" {
type = string
default = null
# validation: PRO | CLASSIC
}
variable "instance_profile_arn" {
type = string
default = null
}
variable "no_wait" {
type = bool
default = null
}
variable "custom_tags" {
type = map(string)
default = {}
}
variable "channel" {
type = object({
name = optional(string)
dbsql_version = optional(string)
})
default = null
}| Output | Description | Sensitive? |
|---|---|---|
id |
ID of the databricks_sql_endpoint resource |
No |
name |
Display name of the warehouse | No |
jdbc_url |
JDBC connection URL β a connection endpoint, not a credential | No |
- Naming discrepancy, restated for a reader who lands here first: this module's folder/product
name is "sql-warehouse," but its keystone resource is
databricks_sql_endpointβdatabricks_sql_warehousehas never existed under that name in this provider. Every.tffile's comments and this README's tagline, Overview, "Schema notes that bite," and Troubleshooting all say this explicitly so a reader searching the registry for "sql_warehouse" isn't left confused. tagsis a nested block, remapped from a plain map.main.tfrendersvar.custom_tags(amap(string)) through adynamic "tags"block wrapping adynamic "custom_tags"block, so the keystone resource receives thetags { custom_tags { key, value } }shape the schema actually requires. A caller only ever writes an ordinary map literal.auto_stop_mins = 10is a house override, not a schema default. The Databricks API itself does not require a caller to set this at all (it is Optional in the schema); this module defaults it to10per this library's secure-by-default convention so a caller must type extra characters (auto_stop_mins = 0or a higher value) to accept more cost exposure, rather than accidentally inheriting a more permissive platform default.enable_serverless_compute/spot_instance_policyinteraction is not enforced viavalidation {}.spot_instance_policyis only meaningful for classic (non-serverless) compute, but this module does not hard-fail a caller who sets both, consistent with the precedent set bytf-mod-databricks-cluster'sautoscale/num_workersjudgment call β over-constraining two fields whose real-world interaction depends on workspace entitlements risks rejecting a legitimate configuration.- No
for_each, no child resources. Example breadth in this README comes from configuration variants (serverless vs. classic, autoscaling, channel, tags) and caller-levelfor_each, not from anything internal to this module.
| Concern | Secure default | Opt-out (caller must set explicitly) |
|---|---|---|
| SQL warehouse auto-stop | auto_stop_mins = 10 |
Caller sets a higher value or 0 (always-on) explicitly β this README's Example 2 carries the mandatory |
This matches this library's secure-by-default convention for "SQL warehouse auto-stop" exactly.
No other argument on this resource carries a house-mandated secure default in v1.0.0 β every other
optional field defaults to null (accept the platform's own default) rather than an invented override, consistent with this library's rule against inventing defaults it doesn't otherwise specify.
cd tf-mod-databricks-sql-warehouse
terraform init -backend=false
terraform validate
terraform fmt -checkPin consumers to an immutable tag β ?ref=v1.0.0 β never a branch. This module is plan-only; a
human applies from CI after review.
terraform validate / terraform fmt -check catch: missing name/cluster_size, the
cluster_size/spot_instance_policy/warehouse_type enum validations, malformed HCL, and β most
importantly for this module β an accidental databricks_sql_warehouse resource block (unsupported
resource type). They do not catch: whether the applying identity actually holds SQL warehouse
creation entitlement, whether serverless SQL compute is actually enabled for the target workspace,
whether a referenced instance_profile_arn actually exists and is attachable, or any other real
Databricks API-side constraint. Those require an actual plan/apply against a live workspace, out
of scope for this authoring process.
$ terraform output
id = "abcdef1234567890"
jdbc_url = "jdbc:databricks://adb-1234567890123456.7.azuredatabricks.net:443/default;transportMode=http;ssl=1;httpPath=/sql/1.0/warehouses/abcdef1234567890;AuthMech=3"
name = "analytics-adhoc"
| Symptom | Cause | Fix |
|---|---|---|
terraform validate fails with Unsupported resource type: databricks_sql_warehouse |
The resource was never renamed from databricks_sql_endpoint despite the product UI calling this a SQL Warehouse |
Use databricks_sql_endpoint; this module already does |
Apply fails with a permissions error even though terraform validate passed |
Applying identity lacks SQL warehouse creation entitlement in the target workspace | Confirm the identity holds the required workspace-level entitlement |
enable_serverless_compute = true fails at apply time |
Serverless SQL compute is not enabled for the workspace | Have a workspace/account admin enable serverless SQL compute, or set enable_serverless_compute = false |
Apply fails referencing an invalid instance_profile_arn |
The instance profile does not exist or is not registered with the workspace | Confirm the ARN and its registration with a workspace admin before reapplying |
terraform plan shows an unexpected diff on every run for custom_tags |
A caller wrote the raw tags { custom_tags {... } } block shape directly against a fork of this module instead of using var.custom_tags |
Use var.custom_tags as documented; let main.tf's dynamic blocks render the nested shape |
| Warehouse never stops even though cost review expected it to | auto_stop_mins was explicitly set to 0 (or a very high value) |
Confirm this was a deliberate, reviewed choice; otherwise reset to the secure default or an appropriate finite value |
databricks_sql_endpointprovider resource β note the URL slug issql_endpoint, notsql_warehouse, consistent with the naming discrepancy explained throughout this README.tf-mod-databricks-sql-query(downstream, consumes this module'sidaswarehouse_id)tf-mod-databricks-permissions(attaches workspace-object ACLs to this warehouse byid)- This module's
SCOPE.md
π "Infrastructure as Code should be standardized, consistent, and secure."