12.2 Databricks Asset Bundles (DAB) Architecture & databricks.yml Structure
Key Takeaways
- Databricks Asset Bundles (DAB) provide an Infrastructure-as-Code (IaC) framework to define, package, test, deploy, and manage complete lakehouse projects (Jobs, DLT Pipelines, ML models) as declarative code.
- The root manifest file is `databricks.yml`, which organizes project definitions into `bundle`, `include`, `variables`, `resources`, and `targets` blocks.
- Resource declarations (`resources: jobs: ...`, `resources: pipelines: ...`) specify task dependencies, cluster configurations, schedules, permissions, and parameters in version-controlled YAML.
- Variables declared under `variables` enable clean parameterization across environments using the substitution syntax `${var.variable_name}` and built-in namespace properties.
- The bundle lifecycle runs through `databricks bundle validate`, `deploy`, `run`, and `destroy`; a bundle can also be deployed straight through the workspace REST APIs as a service principal, but the CLI is preferred because it tracks which resources the bundle already created in that target.
12.2 Databricks Asset Bundles (DAB) Architecture & databricks.yml Structure
As enterprise lakehouses grow in complexity, managing pipelines, scheduled workflows, cluster configurations, and permissions through the web UI becomes error-prone and unscalable. Infrastructure drift between development, staging, and production environments frequently causes deployment failures.
Databricks Asset Bundles (DAB) is Databricks' official Infrastructure-as-Code (IaC) standard. DAB allows data engineers to define complete data engineering projects—including multi-task Lakeflow Jobs, Delta Live Tables (DLT) declarative pipelines, MLflow experiments, custom Python wheels, and notebooks—as declarative, version-controlled YAML and source files.
1. DAB Architecture & Directory Anatomy
A Databricks Asset Bundle project structures source code, resource configuration manifests, and test suites into a modular directory hierarchy:
my_lakehouse_project/
├── databricks.yml # Root bundle configuration manifest
├── resources/ # Modular resource YAML definitions
│ ├── sales_ingest_job.yml # Multi-task Lakeflow Job definition
│ └── telemetry_pipeline.yml # Delta Live Tables pipeline definition
├── src/ # Source code (Python, SQL, Wheels)
│ ├── __init__.py
│ ├── transforms.py
│ └── dlt_bronze_silver.py
├── tests/ # Unit and integration test suites
│ ├── conftest.py
│ └── test_transforms.py
├── fixtures/ # Sample datasets for unit testing
│ └── sample_events.json
└── pyproject.toml # Build configuration for Python wheels
+-------------------------------------------------------------------------+
| DAB COMPILATION & DEPLOYMENT FLOW |
+-------------------------------------------------------------------------+
| |
| 1. LOCAL DEV 2. BUNDLE ENGINE 3. WORKSPACE |
| +--------------------+ +-------------------+ +----------------+ |
| | databricks.yml | | CLI parses YAML | | Workspace File | |
| | resources/*.yml | --> | Interpolates vars | -> | /Users/.. | |
| | src/*.py | | Builds wheels/pkg | | Jobs / DLT API | |
| +--------------------+ +-------------------+ +----------------+ |
| |
+-------------------------------------------------------------------------+
2. The databricks.yml Root Manifest Schema
The databricks.yml file sits at the root of the project. It defines the bundle metadata, file inclusions, variable definitions, and target environments:
# Root bundle identifier
bundle:
name: retail_sales_analytics
# Include modular YAML definitions from the resources/ folder
include:
- resources/*.yml
# Global variable declarations with defaults
variables:
catalog_name:
description: "Target Unity Catalog catalog for Delta tables"
default: "dev_catalog"
schema_name:
description: "Target Unity Catalog schema"
default: "retail"
worker_node_type:
description: "Azure VM node type for compute clusters"
default: "Standard_D4ds_v5"
notification_email:
description: "Email recipient for failure alerts"
default: "dataops-alerts@corp.com"
# Target environment definitions
targets:
dev:
mode: development
default: true
workspace:
host: https://adb-dev.7.azuredatabricks.net
prod:
mode: production
workspace:
host: https://adb-prod.7.azuredatabricks.net
root_path: /Shared/.bundle/${bundle.name}/${bundle.target}
variables:
catalog_name: prod_catalog
worker_node_type: Standard_D8ds_v5
Variable Interpolation Syntax
DAB supports dynamic string interpolation within YAML manifests using the ${...} syntax:
- Custom Variables:
${var.catalog_name},${var.schema_name} - Bundle Context:
${bundle.name},${bundle.target},${bundle.environment} - Workspace Context:
${workspace.current_user.userName},${workspace.current_user.short_name},${workspace.host}
3. Resource Definitions: Jobs & Delta Live Tables Pipelines
Resource configurations define the cloud assets provisioned in Azure Databricks.
Defining a Multi-Task Job (resources/sales_ingest_job.yml)
resources:
jobs:
sales_daily_etl_job:
name: "[${bundle.target}] Daily Sales Processing DAG"
schedule:
quartz_cron_expression: "0 0 4 * * ?"
timezone_id: "UTC"
pause_status: UNPAUSED
email_notifications:
on_failure:
- "${var.notification_email}"
job_clusters:
- job_cluster_key: etl_cluster
new_cluster:
spark_version: "15.4.x-photon-scala2.12"
node_type_id: "${var.worker_node_type}"
autoscale:
min_workers: 2
max_workers: 8
spark_conf:
spark.databricks.delta.preview.enabled: "true"
tasks:
# Task 1: Bronze Ingestion via Python Script
- task_key: ingest_bronze
job_cluster_key: etl_cluster
spark_python_task:
python_file: ../src/ingest_bronze.py
parameters:
- "--catalog"
- "${var.catalog_name}"
- "--schema"
- "${var.schema_name}"
# Task 2: Silver Cleansing (Depends on Bronze Ingestion)
- task_key: transform_silver
depends_on:
- task_key: ingest_bronze
job_cluster_key: etl_cluster
notebook_task:
notebook_path: ../src/notebooks/cleanse_silver.py
base_parameters:
catalog: "${var.catalog_name}"
schema: "${var.schema_name}"
Defining a Delta Live Tables (DLT) Pipeline (resources/telemetry_pipeline.yml)
resources:
pipelines:
telemetry_dlt_pipeline:
name: "[${bundle.target}] Clickstream Telemetry Pipeline"
catalog: "${var.catalog_name}"
target: "${var.schema_name}"
continuous: false
serverless: true
libraries:
- notebook:
path: ../src/dlt_bronze_silver.py
configuration:
pipelines.autoOptimize.zOrderCols: "customer_id,event_timestamp"
4. DAB CLI Commands & Lifecycle Execution
The Databricks CLI provides a suite of bundle commands to manage every stage of the lifecycle:
+-------------------------------------------------------------------------+
| DAB CLI COMMAND EXECUTION LIFECYCLE |
+-------------------------------------------------------------------------+
| |
| 1. VALIDATE 2. DEPLOY 3. RUN & MONITOR |
| $ databricks bundle $ databricks bundle $ databricks bundle run |
| validate deploy -t dev -t dev sales_daily_job |
| | | | |
| v v v |
| Checks syntax, Uploads files, Triggers remote run, |
| schemas & types creates Jobs & DLT streams live output logs |
+-------------------------------------------------------------------------+
CLI Command Matrix
| Command | Purpose | Key Flags & Arguments |
|---|---|---|
databricks bundle init | Generates a new bundle project from built-in or custom templates (default Python, SQL, or MLOps templates). | --template-dir <path> |
databricks bundle validate | Compiles YAML manifests, checks schema validation against Databricks OpenAPI specs, and verifies variable references without deploying. | -t, --target <target> |
databricks bundle deploy | Builds artifacts (e.g., Python wheels), uploads source files to the target workspace path, and creates/updates Jobs and Pipelines. | -t, --target <target>, --force |
databricks bundle run | Executes a specific Job, Pipeline, or Task defined in the bundle in the target environment. | -t, --target <target> <resource_key>, --refresh-all |
databricks bundle destroy | Tears down and deletes all deployed resources (Jobs, Pipelines, uploaded files) in the target environment. | -t, --target <target>, --auto-approve |
databricks bundle schema | Prints the complete JSON schema for databricks.yml to aid IDE autocompletion and validation. | --output <file.json> |
Validating and Deploying via CLI
# Step 1: Validate bundle syntax for the development target
databricks bundle validate -t dev
# Output confirms valid structure:
# Name: retail_sales_analytics
# Target: dev
# Workspace: https://adb-dev.7.azuredatabricks.net
# Valid: true
# Step 2: Deploy bundle to development workspace
databricks bundle deploy -t dev
# Step 3: Trigger a test run of the daily sales job
databricks bundle run -t dev sales_daily_etl_job
5. Deploying Bundle Resources Through the REST API
The DP-750 blueprint lists two bundle deployment bullets: "Deploy a bundle by using the Azure Databricks command-line interface (CLI)" and "Deploy a bundle by using REST APIs." The CLI above covers the first. The second matters whenever the deploying agent is not a shell - an Azure Function, a Logic App, an external orchestrator, or a governance service that must create resources through an authenticated HTTP call.
How the Two Paths Relate
databricks bundle deploy is itself an API client. It resolves the target, interpolates variables, uploads artifacts to the workspace, and then calls the workspace REST APIs to create or update each resource - Jobs, Pipelines, Model Serving endpoints, and so on. Anything the CLI does, an HTTP client can do directly.
| Path | Best for | Trade-off |
|---|---|---|
CLI (databricks bundle deploy -t prod) | GitHub Actions, Azure DevOps, any agent with a shell | Requires the CLI on the runner |
| REST API | Serverless deployers, custom control planes, platforms with no shell | You reimplement target resolution and state management yourself |
Authenticating the Call
Production deployments authenticate as a service principal using an OAuth machine-to-machine token, never a personal access token belonging to an engineer. Section 12.3 covers the run_as identity pattern that pairs with this.
# 1. Exchange the service principal client credentials for an OAuth token
TOKEN=$(curl -s -X POST \
https://adb-prod.7.azuredatabricks.net/oidc/v1/token \
-u "$DATABRICKS_CLIENT_ID:$DATABRICKS_CLIENT_SECRET" \
-d "grant_type=client_credentials&scope=all-apis" | jq -r .access_token)
# 2. Create or update the job the bundle defines
curl -s -X POST \
https://adb-prod.7.azuredatabricks.net/api/2.2/jobs/create \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
--data @resources/daily_sales_job.json
# 3. Create the declarative pipeline the bundle defines
curl -s -X POST \
https://adb-prod.7.azuredatabricks.net/api/2.0/pipelines \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
--data @resources/telemetry_pipeline.json
Why the CLI Is Still the Default Answer
Deploying resource-by-resource over HTTP gives up what the bundle abstraction provides: the CLI knows which resources the bundle previously created in that target, so a redeploy updates them and a databricks bundle destroy removes exactly that set. A hand-rolled REST deployment must track those identifiers itself, or it will create a duplicate job on every run.
Use the REST path when the environment genuinely cannot run the CLI. Otherwise, invoke the CLI and let it call the APIs for you.
6. Artifact Building & Custom Python Wheels
DAB natively manages Python package compilation. If your project contains custom libraries, DAB can automatically build a .whl package and attach it to job tasks:
# Declare artifact build in databricks.yml
artifacts:
core_transforms:
type: whl
path: .
build: "python -m build --wheel"
resources:
jobs:
wheel_processing_job:
name: "[${bundle.target}] Wheel Pipeline"
tasks:
- task_key: execute_wheel
job_cluster_key: etl_cluster
python_wheel_task:
package_name: "retail_core_lib"
entry_point: "process_daily_sales"
parameters:
- "--batch-date=2026-08-26"
libraries:
- whl: ../dist/retail_core_lib-1.0.0-py3-none-any.whl
A data engineer needs to parameterize the Unity Catalog name across multiple YAML resource files in a Databricks Asset Bundle project so that different catalogs are used in development and production. How should this be configured in databricks.yml and referenced in resource files?
Before deploying a complex multi-task job bundle to a shared staging workspace, a data engineer wants to verify that all YAML syntax is correct, resource dependencies are properly structured, and all variable references resolve without actually creating or modifying any workspace assets. Which CLI command should they run?
In a Databricks Asset Bundle multi-task job definition, how is a task configured to execute only after an upstream ingestion task completes successfully?