DAG Versioning & Bundles
Which Version of a DAG Actually Ran?
Before Airflow 3.0, a DAG's code was a single mutable thing on disk - if you edited a DAG file while old runs were still in progress or under investigation, there was no clean record of exactly which version of the code produced which historical run. DAG Versioning fixes that directly.
This is an Airflow 3.0-only feature. This sandbox runs 2.10.0, so there's no live screenshot here - the code and behavior described below are accurate for 3.x.
What Changed
In Airflow 3.0, every time a DAG's structure changes (tasks added/removed, dependencies changed), Airflow records a new DAG version. Each DAG Run is permanently associated with the exact version of the DAG that was active when it ran — so looking at a run from three weeks ago shows the Graph View as it was then, not as the DAG looks today.
# No special code needed to opt in - versioning happens automatically
# whenever the DAG's structure changes between parses
@dag(schedule="@daily", start_date=datetime(2024, 1, 1))
def my_pipeline():
...
Nothing about writing the DAG changes. The difference is entirely in what the UI shows you afterward: a version selector on the DAG's page, letting you view the Graph as it existed for any historical run.
Bundles — Where Versioned Code Actually Lives
A DAG Bundle is Airflow 3's abstraction for where DAG code comes from — a Git repository, a local path, or cloud storage — decoupled from the scheduler and workers needing direct filesystem access to it:
# airflow.cfg or environment-based bundle configuration
dag_bundle_config_list:
- name: production_dags
classpath: airflow.dag_processing.bundles.git.GitDagBundle
kwargs:
repo_url: "https://github.com/my-org/airflow-dags.git"
tracking_ref: "main"
This is the 3.0-native replacement for the git-sync sidecar / shared-volume patterns covered in the Architecture module for keeping DAG files in sync across a distributed deployment — Airflow itself now understands "here's a Git repo, keep it checked out and track its commits" as a first-class concept, rather than relying on external tooling to keep a shared filesystem updated.
Before Bundles, "which commit of our DAGs repo is actually deployed to this Airflow environment right now" was often answered by SSHing into a worker and checking a file's git log by hand. Bundles make that a first-class, queryable piece of Airflow's own state.