Tasks, dependencies, and the job graph
kept in this browser
Edit this pageThe tasks of a job form a DAG. Dependencies set the order; the run-if condition decides whether a task starts based on the outcome of the tasks upstream.
Checked against the Databricks documentation on · history
On this page9
What it is
Dependencies tell a job in which order to run its tasks. The set of tasks and dependencies is a DAG (directed acyclic graph): a task starts only when every task it depends on has finished, and tasks with no dependency between them run in parallel.
Why it exists
A real ETL is not a sequence. Orders and customers can be ingested in parallel, the join has to wait for both, the dashboard has to wait for the join. Describing this as a graph buys you two things: automatic parallelism wherever possible and, when something fails, the ability to restart from the right point (see Repair runs, retries, and notifications).
How it works
Declaring dependencies
In the UI you pick “Depends on” inside the task. In the API and in bundles you use depends_on with the list of upstream task_keys:
tasks:
- task_key: ingest_orders
notebook_task: { notebook_path: ./ingest_orders.py }
- task_key: ingest_customers
notebook_task: { notebook_path: ./ingest_customers.py }
- task_key: join
depends_on:
- { task_key: ingest_orders }
- { task_key: ingest_customers }
notebook_task: { notebook_path: ./join.py }
ingest_orders and ingest_customers do not depend on each other: they run together. join starts once both have finished.
The run-if condition
By default a task starts only if all upstream tasks succeeded. You can change that rule with run_if:
run_if | The task starts if… |
|---|---|
ALL_SUCCESS (default) | all upstream tasks succeeded |
AT_LEAST_ONE_SUCCESS | at least one succeeded |
NONE_FAILED | none failed (success or skipped are both fine) |
ALL_DONE | all have finished, whatever the outcome |
AT_LEAST_ONE_FAILED | at least one failed |
ALL_FAILED | all failed |
ALL_DONE is the usual choice for a cleanup or notification task that must always run. AT_LEAST_ONE_FAILED is for a task that handles the error (for example, writing to an audit table).
- task_key: notify_outcome
depends_on: [{ task_key: join }]
run_if: ALL_DONE
notebook_task: { notebook_path: ./notify.py }
Task states
Every task in a run ends in a state: SUCCESS, FAILED, SKIPPED (dependencies not satisfied), CANCELED, TIMED_OUT, plus UPSTREAM_FAILED / UPSTREAM_CANCELED when an upstream task is what blocked it. In the run’s graph view these states are color-coded: the fastest way to see where a job broke is to read the graph, not the logs.
Tasks and compute
Different tasks can use different compute: a notebook on serverless, a SQL task on a warehouse, a pipeline on its own compute. Dependencies work the same way. With classic job clusters, tasks that share the same job_cluster_key reuse the cluster within the run.
Example
A diamond-shaped graph with error handling:
ingest_orders ───┐
├─► join ─► aggregate ─► refresh_dashboard
ingest_customers ┘ │
└─► audit_errors (run_if: AT_LEAST_ONE_FAILED)
If aggregate fails, refresh_dashboard becomes UPSTREAM_FAILED and audit_errors starts. After the fix, a repair run reruns only aggregate and refresh_dashboard.
Common mistakes
- Building a linear chain
a → b → c → dwhenbandcare independent: you lose parallelism and the run takes longer. - Using
ALL_DONEon a task that writes “final” data: it will run even when the upstream data is incomplete. - Expecting a dependency to pass data: dependencies only govern order. To pass values between tasks you use task values (see Job and task parameters, dynamic values, and task values).
- Forgetting that a
SKIPPEDtask is not an error: with the defaultALL_SUCCESSthe downstream tasks do not start, but the run can still end up as “success with skips”.
Exam hints
Rewritten from real exam questions: what gets asked and where people slip.
- The exam checks that Depends On defines the job DAG: a task waits for its upstream task before it can run. The trap is treating it as a way to share libraries, replace tasks, or tune compute. Remember: dependencies control order; run conditions control outcome logic.
- The exam checks how Lakeflow Jobs order tasks in a DAG. The common trap is reversing the dependency edge or treating a clone as scheduling logic. Rule: make the task that must finish first an upstream dependency of the task that must wait.
- The exam checks whether you understand a Lakeflow Jobs DAG: dependencies define task order. The common trap is reversing the dependency or assuming a cloned task changes execution order. Rule: the later task depends on the task that must finish first.
Where this sits
- Data Engineer AssociateWorking with Lakeflow Jobs16% of the exam“Configure common tasks (notebook, SQL query, dashboard, and pipeline tasks) and their dependencies using Lakeflow Jobs and its DAG-based task graph”
- Data Engineer AssociateTroubleshooting, Monitoring, and Optimization10% of the exam“Use the Lakeflow Jobs UI to monitor pipeline health by interpreting job statuses, viewing DAG-based task graphs to spot upstream blockers, and tracking pipeline run times and failure rates”
- Learning pathData EngineeringBuild production pipelines: ingest with Auto Loader, COPY INTO and Lakeflow Connect, trans…
Nothing of that kind here yet. Try the full list.