Update your Terraform configuration to use Autoscaling resources

This guide walks you through updating an existing Terraform configuration to use Lakebase Autoscaling resources (databricks_postgres_project, databricks_postgres_branch, databricks_postgres_endpoint, databricks_postgres_catalog, databricks_postgres_synced_table).

When this applies

Before following this guide, confirm your Lakebase instance has been upgraded to Autoscaling. Since March 12, 2026, new Lakebase instances created through the Database instance API are created as Autoscaling projects — your Terraform configuration is the only part that still references them using databricks_database_instance. Existing Provisioned instances are also being automatically upgraded to Autoscaling starting June 2026. In both cases, the Terraform configuration update steps are the same. See "Confirm your instance is on Autoscaling" section below to find out whether your Database Instance has been successfully migrated or not yet.

How the update works

The update is in-place. Your data is not moved or copied. Terraform stops tracking the Provisioned resources and starts managing the same underlying database through the Autoscaling resources, unlocking capabilities like scale-to-zero and branching.

The change takes exactly two terraform apply calls: one to adopt the Autoscaling resources, and one to remove the Provisioned ones from Terraform state.

For the conceptual differences between Provisioned and Autoscaling, see Autoscaling by default. This page covers only the Terraform configuration update.

Prerequisites

Before you begin, you need:

  • Terraform 1.7 or higher. The import block and the removed block together require Terraform 1.7+.
  • A service principal configured for OAuth machine-to-machine (M2M) authentication with CAN MANAGE permission on the project. See Authorize service principal access to Azure Databricks with OAuth and Manage project permissions.
  • An existing Lakebase database currently managed by Terraform as databricks_database_instance. If your setup includes a child instance, a databricks_database_database_catalog, or a databricks_database_synced_database_table, this guide covers those too. See "Confirm your instance is on Autoscaling" section below to find out whether your Database Instance has been successfully migrated or not yet.
  • If you have a synced table to update to Autoscaling Terraform, this guide assumes that the source Delta table already exist in Unity Catalog with an id INTEGER NOT NULL column. This guide refers to it as main.default.orders; substitute your real source table's full name.

Switching an app from a databricks_database_instance to a databricks_postgres_project resource is not yet covered.

Confirm your instance is on Autoscaling

Before updating your Terraform configuration, confirm the upgrade to Autoscaling has completed for your Database Instance. The import blocks in Step 2 adopt an Autoscaling project, branches, and endpoints that only exist after the upgrade finishes.

To check:

  1. open the Provisioned page in the Lakebase app, find your instance, and click through to the instance page.
  2. A banner on the instance page confirms whether the upgrade has completed successfully.
  3. Click the "Go to autoscaling UI". When you're in the Autoscaling UI Project page, click "Settings". Find the Resource name, click on two squares near the Resource name input field to copy the Autoscaling Project Resource name. You will be using it to reference the resources in the Terraform import block.

If the upgrade hasn't finished yet, wait until it does before proceeding. To request an expedited upgrade, contact your account team or Databricks Support.

Resource mapping

Provisioned Autoscaling
Parent databricks_database_instance databricks_postgres_project plus an implicitly created production branch
Parent instance's read-write endpoint databricks_postgres_endpoint with endpoint_id = "primary" on the production branch
Parent instance HA (node_count, readable secondaries) a compute group on the production endpoint's spec
Child databricks_database_instance (optional) databricks_postgres_branch whose branch_id equals the child instance's name
Child instance's read-write endpoint databricks_postgres_endpoint with endpoint_id = "primary" on the child branch
databricks_database_database_catalog (optional) databricks_postgres_catalog with the same catalog_id
databricks_database_synced_database_table (optional) databricks_postgres_synced_table with the same synced_table_id

Every Provisioned instance maps to a branch named production on its Autoscaling project. A child instance is the exception: it maps to a separate branch whose branch_id equals the child instance's name.

The project ID is your parent instance's name, lowercased — if the name has uppercase letters, the project ID is the lowercased form. Confirm it in the Databricks UI before importing. All branch import IDs use that project ID as the project segment, even for the child branch.

Step 1: Starting state (Provisioned)

Your starting configuration looks like this. The names my-instance, my-child, my-catalog, my_db, and main.default.orders are placeholders; use whatever names your real resources already have. The root instance here is HA (a primary plus a readable secondary); if yours isn't, leave out node_count and enable_readable_secondaries. The catalog and synced table blocks are optional — keep only the ones your configuration already uses.

terraform {
  required_providers {
    databricks = {
      source = "databricks/databricks"
    }
  }
}

resource "databricks_database_instance" "root" {
  name     = "my-instance"
  capacity = "CU_2"
  node_count                  = 2
  enable_readable_secondaries = true
}

resource "databricks_database_instance" "child" {
  name     = "my-child"
  capacity = "CU_2"
  parent_instance_ref = {
    name = databricks_database_instance.root.name
  }
}

resource "databricks_database_database_catalog" "cat" {
  name                          = "my-catalog"
  database_instance_name        = databricks_database_instance.root.name
  database_name                 = "my_db"
  create_database_if_not_exists = true
}

resource "databricks_database_synced_database_table" "syt" {
  name                  = "my-catalog.default.orders_synced"
  logical_database_name = databricks_database_database_catalog.cat.database_name
  spec = {
    scheduling_policy                  = "SNAPSHOT"
    source_table_full_name             = "main.default.orders"
    primary_key_columns                = ["id"]
    create_database_objects_if_missing = true
    new_pipeline_spec = {
      storage_catalog = "main"
      storage_schema  = "default"
    }
  }
}

Step 2 (Apply 1): Adopt the Autoscaling resources

Add the new Autoscaling resources alongside the existing Provisioned ones. Keep the existing databricks_database_instance blocks in the configuration — the new Autoscaling resources sit next to them. The project and both branches use an import block. The two endpoints (the production branch's and the child branch's) use replace_existing = true instead of an import block, because endpoints don't support standard import blocks today. terraform plan will show the endpoints as "will be created", which is expected behavior for the migration purposes — nothing is recreated server-side, your resources are safe.

# In Lakebase Autoscaling, the parent database instance is represented
# by a project plus an implicitly created "production" branch.
resource "databricks_postgres_project" "root" {
  project_id = "my-instance"  # use the ID from section "Confirm your instance is on Autoscaling"
  spec       = null
}

# Branch corresponding to the parent database_instance.
resource "databricks_postgres_branch" "production" {
  branch_id = "production"
  parent    = databricks_postgres_project.root.name
  spec      = null
}

# Branch corresponding to the child database_instance.
resource "databricks_postgres_branch" "child" {
  branch_id = "my-child"
  parent    = databricks_postgres_project.root.name
  spec      = null
  # spec = null is required during adoption. Setting any spec field causes
  # Terraform to write that value on apply. Fields like source_branch,
  # source_branch_lsn, and endpoint_type are immutable in Lakebase —
  # specifying them forces Terraform to replace (delete and recreate) the
  # resource instead of importing it cleanly. After adoption is complete
  # you can populate mutable fields (such as is_protected) to manage the
  # branch going forward. To look up the source branch, read it from
  # Branch.status.source_branch.
}

# The child branch's primary read-write endpoint.
# Pick one of the spec variants from the tabs below.
resource "databricks_postgres_endpoint" "child_rw_endpoint" {
  endpoint_id = "primary"
  parent      = databricks_postgres_branch.child.name
  spec = {
    endpoint_type = "ENDPOINT_TYPE_READ_WRITE"
  }
  replace_existing = true
}

# The production branch's primary read-write endpoint. Because the parent
# instance is HA, its HA carries over here as a compute `group` (see the
# "Preserving HA" note below). If your parent instance isn't HA, drop the
# `group` and `no_suspension` and keep only `endpoint_type`. If
resource "databricks_postgres_endpoint" "production_rw_endpoint" {
  endpoint_id = "primary"
  parent      = databricks_postgres_branch.production.name
  spec = {
    endpoint_type = "ENDPOINT_TYPE_READ_WRITE"
    no_suspension = true
    group = {
      min                         = 2
      max                         = 2
      enable_readable_secondaries = true
    }
  }
  replace_existing = true
}

# Import the project. Postgres resources use the canonical
# "projects/{project_id}" form as the import ID, where project_id is
# the resource name from section "Confirm your instance is on Autoscaling",
# with "projects/" prefix stripped off.
import {
  to = databricks_postgres_project.root
  id = "projects/my-instance"
}

# Import the production branch. The Provisioned parent always maps to
# a branch named "production" on the new project.
# Use the resource name from section "Confirm your instance is on Autoscaling",
# append "/branches/production" to it.
import {
  to = databricks_postgres_branch.production
  id = "projects/my-instance/branches/production"
}

# Import the child branch. Use the resource name from section
# "Confirm your instance is on Autoscaling", same as when importing
# the "production" branch above. The branch segment is the child instance's name.
import {
  to = databricks_postgres_branch.child
  id = "projects/my-instance/branches/my-child"
}

# The catalog. Pin `catalog_id` to the same name your
# databricks_database_database_catalog already uses, written as a
# literal so the new resource does not depend on the old one. `spec
# = null` is required during adoption — see the "Why spec = null on
# catalog and synced table" note below.
resource "databricks_postgres_catalog" "cat" {
  catalog_id = "my-catalog"
  spec       = null
}

import {
  to = databricks_postgres_catalog.cat
  id = "catalogs/my-catalog"
}

# The synced table. Pin `synced_table_id` to the same fully-qualified
# name your databricks_database_synced_database_table already uses,
# again as a literal.
# `depends_on` is required to build the correct Terraform dependency graph,
# for correct resource management.
resource "databricks_postgres_synced_table" "syt" {
  synced_table_id = "my-catalog.default.orders_synced"
  spec            = null
  depends_on = [
    databricks_postgres_catalog.cat
  ]
}

import {
  to = databricks_postgres_synced_table.syt
  id = "synced_tables/my-catalog.default.orders_synced"
}

For the endpoint's spec, choose one of the variants below.

Note

Why spec = null on catalog and synced table. Today, after terraform import, the catalog and synced table's spec comes back empty from the provider's Read (the input fields inside spec are treated as write-only). If you leave spec populated in HCL, Terraform diffs the populated HCL against the empty state and plans to destroy and re-create the resource. Setting spec = null gives Terraform nothing to diff, so the import sticks. Your data isn't touched — the server already has the correct configuration from when the Provisioned resources were created. The spec fields are also IMMUTABLE on these resources, so even if you could put values in HCL, you couldn't change them afterwards. Endpoints, projects, and branches don't need spec = null because their spec round-trips through Read correctly.

Only import the Autoscaling resources

Adopt the existing endpoint as-is. No behavior change on the server side during the adoption.

spec = {
  endpoint_type = "ENDPOINT_TYPE_READ_WRITE"
}

Use Autoscaling feature during the import

Adopt the child endpoint and override its Autoscaling range in the same terraform apply. After the platform upgrade the endpoint is already autoscaling with a default range — MIN CU 8 for an endpoint adopted from a CU_2 instance, scale-to-zero off. Setting limits here overrides that default range (and, on non-HA endpoints, lets you enable scale-to-zero) without a separate apply. See Compute size for why MIN is 8 and how to pick MIN and MAX values.

spec = {
  endpoint_type            = "ENDPOINT_TYPE_READ_WRITE"
  autoscaling_limit_min_cu = 4
  autoscaling_limit_max_cu = 16
}

Note

Preserving HA. The production endpoint above carries the parent instance's HA as a compute group: min and max equal the instance's node_count, and enable_readable_secondaries matches the instance. HA endpoints must set no_suspension = true, so an HA endpoint can't also scale to zero.

Either choice is a single terraform apply.

Run terraform apply.

Step 3 (Apply 2): Remove the Provisioned resources from Terraform state

Once you are sure the Autoscaling resources are managing your database correctly, drop the original databricks_database_instance blocks from Terraform state. Use a removed block with lifecycle.destroy = false so Terraform stops managing the Provisioned resource without deleting any data.

Remove the databricks_database_instance blocks and any databricks_database_database_catalog / databricks_database_synced_database_table blocks from the configuration, then add a removed {} block for each.

removed {
  from = databricks_database_synced_database_table.syt
  lifecycle {
    destroy = false
  }
}

removed {
  from = databricks_database_database_catalog.cat
  lifecycle {
    destroy = false
  }
}

removed {
  from = databricks_database_instance.child
  lifecycle {
    destroy = false  # it is crucial to set destroy = false. Not doing so results in your database being deleted.
  }
}

removed {
  from = databricks_database_instance.root
  lifecycle {
    destroy = false
  }
}

Run terraform apply.

In the plan output, you will see lines like:

# databricks_database_instance.root will no longer be managed by Terraform, but will not be destroyed
# (destroy = false is set in the configuration)
...
... and similar entry for each of the resource you have used removed block for.
...

This is expected. The data stays. Terraform just stops tracking the Provisioned resource and now manages your database through the Autoscaling resources you adopted in step 2.

Postgres roles and databases

Once the Autoscaling resources are in your configuration, you can use Terraform to create and update Postgres roles and databases going forward via databricks_postgres_role and databricks_postgres_database. Roles and databases that already exist in your database but are not declared in Terraform will not be removed — Terraform only destroys resources it tracks in state. Importing roles and databases that existed before the configuration update is not yet supported. See the databricks_postgres_role and databricks_postgres_database reference pages, or Typical Lakebase project setup with Terraform for a complete example.

Like the production branch and primary endpoint, every Autoscaling project also has an implicitly created role and database.

What's possible now that you've upgraded

Once your project is managed as Autoscaling, you can do things that weren't available on Provisioned. Some highlights:

For a complete production-ready Terraform configuration that uses many of these together, see Typical Lakebase project setup with Terraform.

See also