Migrating from Apache Airflow 2 to 3: What Breaks and What Gets Better

Eric Greene June 11, 2026

Airflow 3.0 went GA in April 2025, and with the 3.2.x line now mature, most teams we work with have stopped asking whether to migrate and started asking what will break. That is the right question. Airflow 3 is the largest architectural change the project has shipped since 2.0, and while the upgrade is very manageable, it is not a drop-in. We have now walked several teams through it, and the same handful of issues come up every time. Here is what we tell them.

The import surface: airflow.sdk replaces internal reaching

The single most common source of breakage is imports. For years, DAG authors imported from wherever worked: airflow.models, airflow.utils, deep internal modules that were never really public API. Airflow 3 draws a hard line with the Task SDK — the airflow.sdk namespace is now the supported surface for DAG authors. DAG, dag, task, Param, context helpers: they all live there now.

# Airflow 2 — imports scattered across internal modules
from airflow.models import DAG
from airflow.decorators import dag, task
from airflow.models.param import Param

# Airflow 3 — one supported surface for DAG authors
from airflow.sdk import DAG, Param, dag, task

The practical migration step is mechanical but tedious: grep your DAG repository for from airflow.models import and from airflow.utils, and move each import to its airflow.sdk equivalent. The ruff rules that ship with the official upgrade tooling catch most of these automatically, and we strongly recommend running them in CI before you touch a single environment — you can make your DAG files forward-compatible while still running Airflow 2, which shrinks the actual cutover to almost nothing.

The reason behind the new namespace matters more than the namespace itself. In Airflow 3, workers no longer talk directly to the metadata database. Tasks execute against an API layer, which is what makes remote execution and language-agnostic workers possible. Any task code that opened a SQLAlchemy session against the Airflow DB — and we have seen plenty of it in the wild — will break, and it should. Audit for Session, provide_session, and direct Variable.set patterns inside task code now.

Datasets become Assets, and scheduling grows up

Airflow 2.4 introduced Datasets for data-aware scheduling. Airflow 3 renames them to Assets and substantially expands the idea. The rename itself is a find-and-replace (DatasetAsset), but the new @asset decorator changes how you can structure pipelines: you define the asset as the unit of interest, and the materializing task comes along with it. Combined with event-driven scheduling, you can now trigger work from external events rather than polling on a cron, which eliminates a whole category of sensor-shaped workarounds.

If your DAGs are still purely time-scheduled, nothing forces you to adopt assets during migration. But if you have sensor chains waiting on upstream tables, this is the feature that pays for the upgrade.

Two scheduling-adjacent removals will bite some teams:

  • SubDAGs are gone. Removed entirely, not deprecated. TaskGroups have been the replacement since 2.0, and the conversion is usually straightforward — TaskGroups are a UI grouping, not separate DAG runs, so check anything that relied on SubDAG-level concurrency controls.
  • SLAs are gone. The old SLA mechanism — long unreliable, as anyone who depended on sla_miss callbacks knows — has been removed and replaced by Deadline Alerts, which are evaluated by the scheduler against a deadline you express relative to the run. If you have alerting built on SLA misses, plan a real redesign here, not a rename.

The new runtime shape: api-server, dag processor, and executors

Operationally, Airflow 3 looks different on a process diagram. The webserver is replaced by the api-server, which serves both the new React UI and the execution API that workers use. The dag processor is now a mandatory standalone component rather than something the scheduler does on the side. If you deploy with the official Helm chart this is mostly handled for you, but if you run systemd units or homegrown containers, your topology changes: airflow api-server and airflow dag-processor are new entries in your process list.

Authentication is rebuilt too. The Flask-AppBuilder auth manager is no longer the default — Airflow 3 ships SimpleAuthManager out of the box, and FAB survives as a provider package for teams that need their existing users, roles, and LDAP wiring. Budget time for this if you have customized FAB security; it works, but it is now an explicit dependency you install and configure rather than something that comes along silently.

On the executor front, the hybrid CeleryKubernetesExecutor (and its LocalKubernetes sibling) is removed. The replacement is better: Airflow 3 supports multiple executors simultaneously, configured as a list, with per-task executor selection. The same mechanism that retired the hybrid executors also enables the new Edge Executor, which lets workers run in remote locations — other networks, other clouds — communicating over HTTP rather than needing a database connection. For teams with data that cannot leave a particular environment, this is genuinely new capability.

What you get for free

Two improvements require no migration work at all and are, in our experience, what teams end up loving. First, DAG versioning is automatic: Airflow 3 tracks the version of the DAG code each run executed against, so the UI finally shows you the graph as it was, not as it is now. Debugging a failure from last Tuesday no longer means archaeology in git. Second, the rewritten UI on the api-server is dramatically faster on large instances, and because the grid and graph views understand versions, in-flight runs are no longer corrupted visually by a mid-run deploy.

A migration order that works

Our recommended sequence: upgrade to the latest Airflow 2.11 first, since it backports compatibility shims; run the ruff upgrade checks and fix imports while still on 2.x; remove SubDAGs and SLA callbacks; verify no task code touches the metadata DB; then cut over environments dev-to-prod with the standalone dag processor and api-server in your deployment definitions from day one. Done in that order, the cutover itself is an afternoon, not a quarter.

If your team is planning this migration, we cover the Airflow 3 architecture, the Task SDK, and asset-based scheduling hands-on in Apache Airflow Programming: Developing, Configuring, and Automating Workflows, and for teams running on Kubernetes, Apache Airflow for Developers (Kubernetes) works through executor configuration and deployment topology in depth.