What you will be able to do
- Define dev, staging and production targets in databricks.yml and select one with -t
- Predict how target settings join with and override top-level resource settings by job_cluster_key, label and task_key
- Configure per-target workspace host, root_path, deployment mode and run_as identity for promotion
1.Targets: one configuration, several destinations
A bundle has exactly one databricks.yml at its root. Its top-level mappings (resources, workspace, artifacts, variables) are the defaults for every environment. The targets mapping lists the environments you deploy to. Under each target you can override workspace, resources, artifacts, variables, run_as, permissions, mode, presets and more. Only one target can be marked default: true.
The simplest promotion step is to point a prod target at a different workspace and a different cluster. Everything you don't override falls back to the top-level definition.
targets:
dev:
default: true
prod:
workspace:
host: https://<production-workspace-url>
resources:
jobs:
hello-job:
name: hello-job
tasks:
- task_key: hello-task
existing_cluster_id: 2345-678901-fabcd456The prod target does not repeat notebook_task. It inherits it from the top-level job. The docs' first example reads its credentials from a local profile named DEFAULT. Databricks recommends the host mapping instead of the default mapping wherever possible, because it makes your bundle configuration files more portable. That advice is about how credentials are found, not about default: true, which only chooses the target used when you pass no -t. The CLI matches the host to a profile in .databrickscfg. If several profiles match, you must pass --profile.
You choose a target with -t (or --target) on validate, deploy and run. Commands without -t go to the default target.
# You must specify "-t prod", because the "dev" target
# is already set to "default: true":
databricks bundle validate
databricks bundle deploy -t prod
databricks bundle run -t prod hello_jobA note on names: the docs' YAML declares the job under the key hello-job, but its run commands say hello_job. The sources do not explain the difference, so treat it as an inconsistency in the docs. In your own bundle, pass bundle run the resource key exactly as it is written in your YAML, as the run_as example does with databricks bundle run my_test_job_1.
Checkpoint 1 of 5· Check yourself
dev is marked default: true and prod overrides the cluster. A CI script runs databricks bundle deploy -t prod and then databricks bundle run hello_job, with no -t on the second command. Where does the run go?
-t applies to each command separately. A command without it uses the target marked default: true, so the run goes to dev. To run in prod you must pass -t prod on that command too.
“You must specify "-t prod", because the "dev" target”Source: docs.databricks.com
Checkpoint 2 of 5· Exam question
How does an engineer declare a bundle variable in `databricks.yml` whose default value is a structured object, such as a cluster spec with a Spark version and worker count, rather than a single string?
Correct answer: A — Set `type: complex` on the variable and give it an object as its `default` value, such as a mapping of Spark version and worker count.
- A. Setting `type: complex` tells the bundle schema to accept a structured object as the variable's value, and the `default` key is where that object, such as a Spark version and worker count mapping, is supplied. This is the documented way to define complex bundle variables.
- B. `type: object` is not a recognized bundle variable type, and splitting nested keys into separate top-level variables with a naming convention does not reconstruct a single structured value at reference time. The bundle schema only supports `complex` for this purpose.
- C. Omitting `type` causes the bundle parser to treat the variable as a plain string rather than inferring a nested structure from a YAML anchor. The `type: complex` declaration is required for the parser to accept an object as the default.
- D. A `--var` flag only accepts simple string values on the command line and cannot express a nested object, so a complex variable's structured default must still be defined inside `databricks.yml` itself. The `default` key is where that structure belongs, not a CLI flag.
Sources1
2.How target overrides merge with top-level settings
A target override does not replace the whole resource. It is joined with the top-level definition, and where both set the same field, the target's value wins. For list entries such as job clusters, pipeline clusters and tasks, the bundle needs a key to know which entries to merge.
| What you override | Matching key | Where it lives |
|---|---|---|
| Job cluster settings | job_cluster_key | resources.jobs.<job>.job_clusters |
| Lakeflow pipeline cluster settings | label (default or maintenance) | resources.pipelines.<pipeline>.clusters |
| Job task settings | task_key | resources.jobs.<job>.tasks |
| Artifact settings | artifact identifier | artifacts.<artifact> |
resources:
jobs:
my-job:
name: my-job
job_clusters:
- job_cluster_key: my-cluster
new_cluster:
spark_version: 13.3.x-scala2.12
targets:
development:
resources:
jobs:
my-job:
name: my-job
job_clusters:
- job_cluster_key: my-cluster
new_cluster:
node_type_id: i3.xlarge
num_workers: 1The validated result has all three fields. If the top level also set num_workers: 1 and the target set num_workers: 2, the result would be 2. Pipelines work the same way, matched on the cluster label. A top-level node_type_id plus a target num_workers on label default produces one cluster with both. Tasks only merge when task_key matches exactly. A target task with a different key is not joined to the top-level task.
Checkpoint 3 of 5· Match them up
Match each override to the key that joins it with the top-level definition
Tap a term, then the definition that fits it.
Each kind of list entry has its own identifier. Settings are joined only when the same identifier appears at the top level and in the target.
“use label within the cluster settings of a pipeline definition to identify cluster settings in a top-level resources mapping”Source: docs.databricks.com
Checkpoint 4 of 5· Exam question
A team wants every resource deployed by their bundle's `prod` target to run under a service principal instead of the deploying engineer's own identity. How should they configure this in `databricks.yml`?
Correct answer: A — Add a `run_as` block under the `prod` target that specifies the service principal's application ID, so deployed resources run under that identity.
- A. A `run_as` block under the `prod` target is the supported way to make deployed jobs and pipelines execute as a service principal rather than the deploying user. It applies to the resources in that target without touching the job definitions themselves.
- B. Granting workspace folder permissions after the fact controls who can view or edit the deployed files, but it does not change which identity the jobs actually run as during execution. The `run_as` field is still required to change the execution identity.
- C. The `mode` field controls deployment behaviors like resource-name prefixing and schedule pausing, not the execution identity of deployed resources. Setting it to `production` has no effect on who the jobs run as.
- D. `run_as` is a target-level (or resource-level) field, not something resolved through a `${var.*}` reference inside job task definitions, so referencing it that way would not be recognized by the bundle schema. The identity must be set through the `run_as` block itself.
Sources2
3.Modes and run identities across dev, staging and prod
Targets also control how a deployment behaves, not just which values it uses. The mode mapping is optional. It applies a group of commonly used settings at once. mode: development is meant for pre-production iteration, and mode: production is meant for validated deliverables.
| Behaviour | mode: development | mode: production |
|---|---|---|
| Lakeflow pipelines | Marked development: true | Validates they are development: false |
| Cluster overrides | Enables --cluster-id on bundle deploy, overriding existing cluster definitions | Does not allow overriding existing cluster definitions |
Development mode also does the following: - prepends the prefix [dev ${workspace.current_user.short_name}] to all resources that are not deployed as files or notebooks - tags each deployed job and pipeline with a dev Databricks tag - pauses all schedules and triggers - enables concurrent job runs - disables the deployment lock
Production mode can also check that the current Git branch matches the branch set in the target. You can override that check with --force.
Databricks recommends service principals for production deployments. If you do not use one, production mode adds two more validations. It checks that artifact_path, file_path, root_path and state_path are not overridden to a specific user. It also checks that run_as and permissions are specified, so it is clear which identities hold which permissions for deployments.
To customise a mode, set presets on the target. Presets override the mode's defaults, and settings on individual resources override presets.
The identity a job runs as is also set per target. Databricks calls it best practice to configure run identities for staging and production. Production should run as a service principal, which keeps the permission to run a workflow separate from the identity that deployed it.
# Staging deployment settings
staging:
workspace:
host: https://my-host.cloud.databricks.com
root_path: /Shared/staging-workspace/.bundle/${bundle.name}/${bundle.target}
run_as:
service_principal_name: '69511ed2-zb27-444c-9863-4bc8ff497637'
# Production deployment settings
production:
mode: production
workspace:
host: https://my-host.cloud.databricks.com
root_path: /Shared/production-workspace/.bundle/${bundle.name}/${bundle.target}
run_as:
service_principal_name: '68ed9cd5-8923-4851-x0c1-c7536c67ff99'Checkpoint 5 of 5· Check yourself
A production target has mode: production. An engineer tries to deploy it with a cluster override flag so the job runs on their personal cluster. What happens?
Development mode enables cluster overrides on deploy. Production mode explicitly does not allow overriding existing cluster definitions.
“setting the mode mapping to production does not allow overriding any existing cluster definitions”Source: docs.databricks.com
Exam traps
Each one states something that sounds right. Open it to see what is actually true.
1.A target that sets only num_workers on a job cluster replaces the whole new_cluster block, so spark_version is lost.Why is that wrong?
Target settings are joined with the top-level settings for the same job_cluster_key. Only fields defined in both places are overridden, and the target wins those.
Covered in How target overrides merge with top-level settings
2.If a preset sets jobs_max_concurrent_runs to 20, every job uses 20, even a job whose own max_concurrent_runs is 10.Why is that wrong?
Presets override the mode defaults, but a setting on an individual resource overrides the preset. That job keeps 10.
Covered in Modes and run identities across dev, staging and prod
Practise it for real
Promote one hello-bundle from dev to prod by changing only variable values and target settings
1.In databricks.yml, declare a variable my_cluster_id with default 1234-567890-abcde123, use existing_cluster_id: ${var.my_cluster_id} in the hello-task, and run databricks bundle validate --output json.
Why: Confirms the variable resolves before anything is deployed.
You should see: The variables section shows my_cluster_id with default and value both 1234-567890-abcde123.
2.Add a prod target with workspace.host set to your production URL, and variables: my_cluster_id: 2345-678901-bcdef234 under it.
Why: A value in the targets mapping is checked before the top-level default.
You should see: Deploying to prod uses 2345-678901-bcdef234. Deploying to dev still uses the default.
3.Run databricks bundle deploy -t dev, then databricks bundle run -t dev hello-job. Here hello-job is the resource key under resources.jobs in your YAML.
Why: dev is the default target, so -t is optional, but stating it makes the CI step explicit. bundle run takes the resource key exactly as written in your YAML.
You should see: A job prefixed [dev <your short name>] if dev uses mode: development, running on the default cluster.
4.Run databricks bundle deploy -t prod, then databricks bundle run -t prod hello-job.
Why: The same files are promoted, and only target-level values change.
You should see: The job is deployed to the production workspace, using the prod cluster ID.
Stuck? Get a nudge
If prod picks up the wrong cluster, look for a BUNDLE_VAR_my_cluster_id environment variable. It takes priority over the target mapping.
Sources
Every claim above is drawn from one of these pages, quoted as it was written on the date shown.
- 1.
“Databricks recommends that you use the host mapping instead of the default mapping wherever possible”
↩︎ Targets: one configuration, several destinations“you do not need to declare the notebook_task mapping within the prod mapping”
↩︎ Targets: one configuration, several destinations“You must specify "-t prod", because the "dev" target”
↩︎ Checkpoint - 2.
“then the setting in the targets mapping takes precedence over the setting in the top-level resources mapping”
↩︎ How target overrides merge with top-level settings“the task mappings' task_key must be set to the same value”
↩︎ How target overrides merge with top-level settings“then the setting in the targets mapping takes precedence over the setting in the top-level resources mapping”
↩︎ Exam trap 1“spark_version in the top-level resources mapping is combined with node_type_id and num_workers in the resources mapping in targets”
↩︎ Prediction“use label within the cluster settings of a pipeline definition to identify cluster settings in a top-level resources mapping”
↩︎ Checkpoint - 3.
“Deployment modes are a convenience for applying a group of commonly used settings at once.”
↩︎ Modes and run identities across dev, staging and prod“Prepends all resources that are not deployed as files or notebooks with the prefix”
↩︎ Modes and run identities across dev, staging and prod“Validates that the run_as and permissions mappings are specified to clarify which identities have specific permissions for deployments.”
↩︎ Modes and run identities across dev, staging and prod“presets override the default mode behavior, and settings of individual resources override the presets”
↩︎ Exam trap 2“setting the mode mapping to production does not allow overriding any existing cluster definitions”
↩︎ Checkpoint - 4.
“It is best practice to configure run identities for staging and production target deployments.”
↩︎ Modes and run identities across dev, staging and prod“Decouples the permission to run the production workflow from the identity that created or deployed the bundle.”
↩︎ Modes and run identities across dev, staging and prod