Skip to main content

Development

Lakebase Postgres development

This page covers developing against Lakebase Postgres from an AppKit app. For Lakebase itself (projects, branches, autoscaling, connectivity), see the Lakebase docs or the databricks-lakebase agent skill.

AppKit plugin API

The lakebase() plugin provides a standard pg.Pool with automatic OAuth token refresh. Once registered, access it via AppKit.lakebase:

import { createApp, lakebase, server } from "@databricks/appkit";

const AppKit = await createApp({
  plugins: [server(), lakebase()],
});

// Standard parameterized query
const { rows } = await AppKit.lakebase.query<{ id: number; name: string }>(
  "SELECT id, name FROM app.items WHERE active = $1",
  [true],
);

// ORM-ready config (Drizzle, Prisma, TypeORM, etc.)
const ormConfig = AppKit.lakebase.getOrmConfig();
// Returns: { host, port, database, ssl, user, ... }

// pg-compatible config
const pgConfig = AppKit.lakebase.getPgConfig();

// Raw pg.Pool for advanced usage
const pool = AppKit.lakebase.pool;

Pool configuration

Override connection pool defaults by passing a pool object:

lakebase({
  pool: {
    max: 10, // max connections (default: 10)
    connectionTimeoutMillis: 5000, // connection timeout ms (default: 10000)
    idleTimeoutMillis: 30000, // idle timeout ms (default: 30000)
  },
});

The max: 10 default applies to the shared service-principal pool. Per-user on-behalf-of pools (created by asUser(req)) default to max: 3.

Caching integration

Lakebase Postgres also backs the AppKit caching plugin when healthy. For the full API, ORM integration, and connection configuration, read the plugin reference.

Auth model

Lakebase Postgres authenticates database connections using OAuth tokens or native Postgres passwords. The method depends on where your app runs.

Deployed apps: When you add it as a resource to a Databricks App, Databricks creates a service principal automatically, grants it a matching Postgres role, and injects connection details as environment variables. AppKit's lakebase() plugin handles OAuth token refresh automatically.

Local development: Your personal Databricks identity connects with an OAuth token generated by databricks postgres generate-database-credential. Tokens expire after one hour, but expiration is enforced only at login. Open connections remain active after the token expires. Run databricks apps deploy at least once before running npm run dev. Local setup explains why order matters and what to do if you hit permission errors.

About authentication covers Postgres password auth, token rotation, and machine-to-machine flows.

Local setup

databricks apps init populates .env with the correct Lakebase Postgres connection values. Run databricks apps deploy before npm run dev. Deploying sets up a managed identity (the app's service principal) that creates the app schema and tables on first startup and owns them. If npm run dev runs first instead, your personal credentials create those objects. The deployed app then can't access them and hits permission denied for schema app.

Local database access

If you created the Lakebase Postgres project, your identity already has the access it needs. After databricks apps deploy runs once, npm run dev works.

For collaborators who need local read/write access, grant them a role on the branch in the Lakebase UI (Roles & Databases). Postgres password auth is an alternative to OAuth: enable password connections, create a password role, then use the password as PGPASSWORD in .env. About authentication has the steps for both.

You can also generate a short-lived credential for use with any PostgreSQL client (DBeaver, pgAdmin, DataGrip, or a language driver):

databricks postgres generate-database-credential \
  projects/my-project/branches/production/endpoints/primary

The AppKit plugin docs: local development cover fine-grained permission alternatives for teams that need schema-scoped access.

Connect with psql

databricks psql opens an interactive PostgreSQL session against a branch endpoint. It requires psql to be installed locally. With no target, it prompts you to pick from the databases you can access.

databricks psql --project my-project
OptionDescription
--autoscalingOnly show Lakebase Autoscaling projects
--projectProject ID
--branchBranch ID (default: auto-select)
--endpointEndpoint ID (default: auto-select)
--max-retriesConnection retries; 0 to disable (default 3)
--debugenable debug logging
--output, -ooutput type: text or json (default text)
--profile, -p~/.databrickscfg profile
--target, -tbundle target to use (if applicable)

Pass extra arguments straight to psql after a -- separator, for example databricks psql --project my-project -- -c "SELECT 1".

Feature branches

Use Lakebase Postgres branches to isolate schema changes and test migrations without affecting production:

databricks postgres create-branch projects/my-project feature-xyz \
  --json '{"spec": {"no_expiry": true}}'
OptionDescription
--jsoneither inline JSON string or @path/to/file.json with request body (default JSON (0 bytes))
--no-waitdo not wait to reach DONE state
--replace-existingIf true, update the branch if it already exists instead of returning an error.
--timeoutmaximum amount of time to reach DONE state
--debugenable debug logging
--output, -ooutput type: text or json (default text)
--profile, -p~/.databrickscfg profile
--target, -tbundle target to use (if applicable)

A primary read-write endpoint is created automatically, inheriting the project's default_endpoint_settings. Branches require an expiration policy (ttl, expire_time, or no_expiry: true). Branch expiration details the available policies.

Delete when done:

databricks postgres delete-branch projects/my-project/branches/feature-xyz
OptionDescription
--no-waitdo not wait to reach DONE state
--purgeIf true, permanently delete the branch; if false, soft delete.
--timeoutmaximum amount of time to reach DONE state
--debugenable debug logging
--output, -ooutput type: text or json (default text)
--profile, -p~/.databrickscfg profile
--target, -tbundle target to use (if applicable)

Off-platform apps

For apps hosted outside Databricks (AWS, Vercel, Netlify, and others), the platform does not inject connection details or refresh OAuth tokens automatically. Token rotation is the app's responsibility. About Lakebase authentication covers token rotation and machine-to-machine patterns. The Lakebase Off-Platform template includes a complete implementation with environment setup and Drizzle ORM integration.

To provision and connect without a template, create a project, read its endpoint and database, then connect:

databricks postgres create-project <project-id>
databricks postgres list-endpoints projects/<project-id>/branches/production -o json
databricks postgres list-databases projects/<project-id>/branches/production -o json
databricks psql --project <project-id>

create-project makes a project with a default production branch, a databricks_postgres database, and a read-write endpoint. If you don't have psql, run databricks postgres generate-database-credential <endpoint-path> and use the returned token as the password (username is your Databricks email) with any PostgreSQL client. See the Lakebase docs or the databricks-lakebase agent skill for the full flow and flags.

The values you need from the list-endpoints and list-databases output:

ValueJSON pathUsed for
Endpoint hoststatus.hosts.hostPGHOST
Endpoint resource pathnameLAKEBASE_ENDPOINT
Database resource pathname (from list-databases)lakebase.postgres.database
PostgreSQL database namestatus.postgres_databasePGDATABASE

Long-running operations

Create, update, and delete commands block until complete by default. Use --no-wait to return immediately and poll status:

databricks postgres create-project my-project \
  --json '{"spec": {"display_name": "My Project"}}' \
  --no-wait

databricks postgres get-operation projects/my-project/operations/<operation-id>

Declarative Automation Bundles

Declarative Automation Bundles (DABs) let you define Lakebase Postgres infrastructure as code in databricks.yml, versioned alongside your application. A bundle specifies postgres_projects, postgres_branches, and postgres_endpoints under resources.

Example databricks.yml with a project, dev branch, and read-only replica
bundle:
  name: my-lakebase-app

resources:
  postgres_projects:
    my_app:
      project_id: "my-lakebase-app"
      display_name: "My Lakebase Postgres App"
      pg_version: 17
      history_retention_duration: "172800s"
      default_endpoint_settings:
        autoscaling_limit_min_cu: 0.5
        autoscaling_limit_max_cu: 1.0
        suspend_timeout_duration: "300s"
        pg_settings:
          log_min_duration_statement: "1000"

  postgres_branches:
    dev_branch:
      parent: ${resources.postgres_projects.my_app.id}
      branch_id: "dev"
      no_expiry: true
      is_protected: false

  postgres_endpoints:
    read_replica:
      parent: ${resources.postgres_branches.dev_branch.id}
      endpoint_id: "replica"
      endpoint_type: "ENDPOINT_TYPE_READ_ONLY"
      autoscaling_limit_min_cu: 0.5
      autoscaling_limit_max_cu: 0.5

Validate and deploy

databricks bundle validate
databricks bundle deploy

bundle deploy is idempotent. It creates new resources and updates existing ones to match the configuration. Unlike Databricks Jobs or Apps, there is no bundle run step. Lakebase Postgres resources are active once deployed. The Declarative Automation Bundles documentation covers all options, and the databricks-dabs agent skill can author and validate bundles.

Update masks

Update commands require an update mask specifying which fields to modify. The --json payload contains the new values. Only masked fields change.

databricks postgres update-branch \
  projects/my-project/branches/production \
  spec.is_protected \
  --json '{"spec": {"is_protected": true}}'

For multiple fields, use a comma-separated update mask (for example, spec.autoscaling_limit_min_cu,spec.autoscaling_limit_max_cu).

Troubleshooting

For Databricks Apps configuration issues (resources in databricks.yml and app.yaml), Add a Lakebase resource to a Databricks app has the resource and environment variable reference. For connection problems including idle wake-up and endpoint format, Troubleshooting in Connect external apps has fixes.

  • permission denied for schema app (deployed app): npm run dev ran before databricks apps deploy, so the schema is owned by your personal credentials and the app's service principal can't access it. (PostgreSQL schema ownership is tied to the role that created it and cannot be reassigned by regular users.) If you have data to preserve, export it first (pg_dump or copy tables to a temporary schema) before dropping. Then drop the schema and redeploy so the SP recreates it on startup: databricks psql --project <project-id> -- -c "DROP SCHEMA IF EXISTS app CASCADE;" then databricks apps deploy.
  • permission denied for schema app (local dev, collaborator): Only the Lakebase project creator gets databricks_superuser access automatically. To grant a teammate local access, the creator adds a role for their identity on the branch (Roles & Databases in the Lakebase UI), or sets up Postgres password auth. See About authentication for the steps.
  • Unknown field path in update_mask: 'spec.suspend_timeout_duration': Use spec.suspension as the update mask for all endpoint-level suspension changes with update-endpoint. To disable scale to zero, pass {"spec": {"no_suspension": true}}. To change the timeout, pass {"spec": {"suspend_timeout_duration": "300s"}}. Setting no_suspension: false is not supported.
  • Connection refused after period of inactivity: Lakebase Autoscaling scales to zero when idle. The first connection after inactivity triggers a wake-up and may be briefly delayed. If your connection library doesn't retry automatically, add a short retry loop.

AppKit docs

Access the AppKit API reference, component docs, and plugin docs from the terminal:

npx @databricks/appkit docs                    # browse the documentation index
npx @databricks/appkit docs "lakebase"         # view Lakebase Postgres plugin docs

Or view the AppKit Lakebase Postgres plugin reference on this site.

Where to next

Templates cover common Lakebase Postgres patterns. Browse them to find a starting point, or copy one into your coding agent to scaffold a working app.

Databricks Developer Hub

Ready to ship your next agentic app in minutes?

Read docs