migrating-airflow-2-to-3

Automatisierte Erkennung und Code-Migration für das Upgrade von Apache Airflow 2.x DAGs auf Airflow 3.x. Bietet Ruff-basierte Auto-Fix-Regeln (AIR30/AIR301/AIR302/AIR31/AIR311/AIR312) zur Erkennung und Behebung von Breaking Changes bei Imports, Operatoren, Hooks und Kontextvariablen. Deckt kritische Architekturänderungen ab: Worker greifen nicht mehr direkt auf die Metadaten-DB zu; stattdessen den Airflow Python Client oder die REST API anstelle von ORM-Sitzungsabfragen verwenden. Enthält eine manuelle Migrations-Checkliste für Probleme, die Ruff nicht automatisch beheben kann: Cron...

npx skills add https://github.com/astronomer/agents --skill migrating-airflow-2-to-3

Airflow 2 to 3 Migration

This skill helps migrate Airflow 2.x DAG code to Airflow 3.x, focusing on code changes (imports, operators, hooks, context, API usage).

Important: Before migrating to Airflow 3, strongly recommend upgrading to Airflow 2.11 first, then to at least Airflow 3.0.11 (ideally directly to 3.1). Other upgrade paths would make rollbacks impossible. See: https://www.astronomer.io/docs/astro/airflow3/upgrade-af3#upgrade-your-airflow-2-deployment-to-airflow-3. Additionally, early 3.0 versions have many bugs - 3.1 provides a much better experience.

Migration at a Glance

  1. Run Ruff's Airflow migration rules to auto-fix detectable issues (AIR30/AIR301/AIR302/AIR31/AIR311/AIR312).
    • ruff check --preview --select AIR --fix --unsafe-fixes .
  2. Scan for remaining issues using the manual search checklist in reference/migration-checklist.md.
    • Focus on: direct metadata DB access, legacy imports, scheduling/context keys, XCom pickling, datasets-to-assets, REST API/auth, plugins, and file paths.
    • Hard behavior/config gotchas to explicitly review:
      • Cron scheduling semantics: consider AIRFLOW__SCHEDULER__CREATE_CRON_DATA_INTERVAL=True if you need Airflow 2-style cron data intervals.
      • .airflowignore syntax changed from regexp to glob; set AIRFLOW__CORE__DAG_IGNORE_FILE_SYNTAX=regexp if you must keep regexp behavior.
      • OAuth callback URLs add an /auth/ prefix (e.g. /auth/oauth-authorized/google).
      • Shared utility imports: Bare imports like import common from dags/common/ no longer work on Astro. Use fully qualified imports: import dags.common.
  3. Plan changes per file and issue type:
    • Fix imports - update operators/hooks/providers - refactor metadata access to using the Airflow client instead of direct access - fix use of outdated context variables - fix scheduling logic.
  4. Implement changes incrementally, re-running Ruff and code searches after each major change.
  5. Explain changes to the user and caution them to test any updated logic such as refactored metadata, scheduling logic and use of the Airflow context.

Architecture & Metadata DB Access

Airflow 3 changes how components talk to the metadata database:

  • Workers no longer connect directly to the metadata DB.
  • Task code runs via the Task Execution API exposed by the API server.
  • The DAG processor runs as an independent process separate from the scheduler.
  • The Triggerer uses the task execution mechanism via an in-process API server.

Trigger implementation gotcha: If a trigger calls hooks synchronously inside the asyncio event loop, it may fail or block. Prefer calling hooks via sync_to_async(...) (or otherwise ensure hook calls are async-safe).

Key code impact: Task code can still import ORM sessions/models, but any attempt to use them to talk to the metadata DB will fail with:

RuntimeError: Direct database access via the ORM is not allowed in Airflow 3.x

Patterns to search for

When scanning DAGs, custom operators, and @task functions, look for:

  • Session helpers: provide_session, create_session, @provide_session
  • Sessions from settings: from airflow.settings import Session
  • Engine access: from airflow.settings import engine
  • ORM usage with models: session.query(DagModel)..., session.query(DagRun)...

Replacement: Airflow Python client

Preferred for rich metadata access patterns. Add to requirements.txt:

apache-airflow-client==<your-airflow-runtime-version>

Example usage:

import os
from airflow.sdk import BaseOperator
import airflow_client.client
from airflow_client.client.api.dag_api import DAGApi

_HOST = os.getenv("AIRFLOW__API__BASE_URL", "https://<your-org>.astronomer.run/<deployment>/")
_TOKEN = os.getenv("DEPLOYMENT_API_TOKEN")

class ListDagsOperator(BaseOperator):
    def execute(self, context):
        config = airflow_client.client.Configuration(host=_HOST, access_token=_TOKEN)
        with airflow_client.client.ApiClient(config) as api_client:
            dag_api = DAGApi(api_client)
            dags = dag_api.get_dags(limit=10)
            self.log.info("Found %d DAGs", len(dags.dags))

Replacement: Direct REST API calls

For simple cases, call the REST API directly using requests:

from airflow.sdk import task
import os
import requests

_HOST = os.getenv("AIRFLOW__API__BASE_URL", "https://<your-org>.astronomer.run/<deployment>/")
_TOKEN = os.getenv("DEPLOYMENT_API_TOKEN")

@task
def list_dags_via_api() -> None:
    response = requests.get(
        f"{_HOST}/api/v2/dags",
        headers={"Accept": "application/json", "Authorization": f"Bearer {_TOKEN}"},
        params={"limit": 10}
    )
    response.raise_for_status()
    print(response.json())

Ruff Airflow Migration Rules

Use Ruff's Airflow rules to detect and fix many breaking changes automatically.

  • AIR30 / AIR301 / AIR302: Removed code and imports in Airflow 3 - must be fixed.
  • AIR31 / AIR311 / AIR312: Deprecated code and imports - still work but will be removed in future versions; should be fixed.

Commands to run (via uv) against the project root:

# Auto-fix all detectable Airflow issues (safe + unsafe)
ruff check --preview --select AIR --fix --unsafe-fixes .

# Check remaining Airflow issues without fixing
ruff check --preview --select AIR .

Reference Files

For detailed code examples and migration patterns, see:


Quick Reference Tables

Key Import Changes

Airflow 2.xAirflow 3
airflow.operators.dummy_operator.DummyOperatorairflow.providers.standard.operators.empty.EmptyOperator
airflow.operators.bash.BashOperatorairflow.providers.standard.operators.bash.BashOperator
airflow.operators.python.PythonOperatorairflow.providers.standard.operators.python.PythonOperator
airflow.decorators.dagairflow.sdk.dag
airflow.decorators.taskairflow.sdk.task
airflow.datasets.Datasetairflow.sdk.Asset

Context Key Changes

Removed KeyReplacement
execution_datecontext["dag_run"].logical_date
tomorrow_ds / yesterday_dsUse ds with date math: macros.ds_add(ds, 1) / macros.ds_add(ds, -1)
prev_ds / next_dsprev_start_date_success or timetable API
triggering_dataset_eventstriggering_asset_events
templates_dictcontext["params"]

Asset-triggered runs: logical_date may be None; use context["dag_run"].logical_date defensively.

Cannot trigger with future logical_date: Use logical_date=None and rely on run_id instead.

Cron note: for scheduled runs using cron, logical_date semantics differ under CronTriggerTimetable (aligning logical_date with run_after). If you need Airflow 2-style cron data intervals, consider AIRFLOW__SCHEDULER__CREATE_CRON_DATA_INTERVAL=True.

Default Behavior Changes

SettingAirflow 2 DefaultAirflow 3 Default
scheduletimedelta(days=1)None
catchupTrueFalse

Callback Behavior Changes

  • on_success_callback no longer runs on skip; use on_skipped_callback if needed.
  • @teardown with TriggerRule.ALWAYS not allowed; teardowns now execute even if DAG run terminated early.

Resources


Related Skills

  • testing-dags: For testing DAGs after migration
  • debugging-dags: For troubleshooting migration issues
  • deploying-airflow: For deploying migrated DAGs to production

Mehr Skills von astronomer

airflow
astronomer
Apache Airflow-DAGs, Ausführungen, Aufgaben und Systemkonfiguration abfragen, verwalten und Fehler beheben. Unterstützt über 30 Befehle für DAG-Inspektion, Ausführungsverwaltung, Aufgabenprotokollierung, Konfigurationsabfragen und direkten REST-API-Zugriff. Mehrere Airflow-Instanzen mit persistenter Konfiguration verwalten; lokale und Astro-Bereitstellungen automatisch erkennen. DAG-Ausführungen synchron (warten auf Abschluss) oder asynchron auslösen, Fehler diagnostizieren, Ausführungen für Wiederholungen löschen und Aufgabenprotokolle mit Wiederholungs-/Kartenindex-Filterung abrufen. Ausgabe...
official
airflow-hitl
astronomer
Menschliche Genehmigungstore, Formulareingaben und Verzweigungen in Airflow-DAGs unter Verwendung von aufschiebbaren Operatoren. Vier Operatortypen: ApprovalOperator für Genehmigen/Ablehnen-Entscheidungen, HITLOperator für Mehrfachauswahl mit Formularen, HITLBranchOperator für menschlich gesteuerte Aufgabenweiterleitung und HITLEntryOperator für Formulardatenerfassung. Alle Operatoren sind aufschiebbar und geben Worker-Slots frei, während sie auf menschliche Antworten über den Bereich "Erforderliche Aktionen" der Airflow-Benutzeroberfläche oder die REST-API warten. Unterstützt optionale Funktionen einschließlich benutzerdefinierter...
official
airflow-plugins
astronomer
Erstellen Sie Airflow 3.1+-Plugins, die FastAPI-Apps, benutzerdefinierte UI-Seiten, React-Komponenten, Middleware, Makros und Operator-Links direkt in die Airflow-Oberfläche einbetten. Verwenden Sie…
official
analyzing-data
astronomer
Fragen Sie Ihr Data Warehouse, um Geschäftsfragen mit zwischengespeicherten Mustern und Konzeptzuordnungen zu beantworten. Unterstützt Mustersuche und Zwischenspeicherung für wiederkehrende Fragetypen, mit Aufzeichnung der Ergebnisse zur Verbesserung zukünftiger Abfragen. Enthält eine Konzept-zu-Tabelle-Zuordnungs-Cache und Tabellenschema-Erkennung über INFORMATION_SCHEMA oder Codebase-Grep. Bietet run_sql()- und run_sql_pandas()-Kernel-Funktionen, die Polars- oder Pandas-DataFrames für Analysen zurückgeben. CLI-Befehle zur Verwaltung von Konzept-, Muster- und Tabellen-Caches, plus...
official
annotating-task-lineage
astronomer
Annotieren von Airflow-Tasks mit Data Lineage mithilfe von Inlets und Outlets. Unterstützt OpenLineage-Dataset-Objekte, Airflow-Assets und Airflow-Datasets zur Definition von Ein- und Ausgaben über Datenbanken, Data Warehouses und Cloud-Speicher hinweg. Verwenden Sie es als Fallback, wenn Operatoren keine integrierten OpenLineage-Extraktoren besitzen; folgt einem vierstufigen Prioritätssystem, bei dem benutzerdefinierte Extraktoren und OpenLineage-Methoden Vorrang haben. Enthält Dataset-Namenshilfen für Snowflake, BigQuery, S3 und PostgreSQL, um eine konsistente...
official
authoring-dags
astronomer
Geführter Workflow zur Erstellung von Apache Airflow DAGs mit Validierungs- und Testintegration. Strukturierter Sechs-Phasen-Ansatz: Umgebung und bestehende Muster erkunden, DAG-Struktur planen, Implementierung nach Best Practices, Validierung mit af CLI-Befehlen, Testen mit Benutzereinwilligung und Iteration über Fehlerbehebungen. CLI-Befehle zur Erkundung (af config connections, af config providers, af dags list) und Validierung (af dags errors, af dags get, af dags explore) bieten sofortiges Feedback zu DAG...
official
blueprint
astronomer
Wiederverwendbare Airflow-Task-Gruppen-Vorlagen mit Pydantic-Validierung definieren und DAGs aus YAML zusammenstellen. Verwenden beim Erstellen von Blueprint-Vorlagen, Zusammenstellen von DAGs aus…
official
checking-freshness
astronomer
Überprüft die Datenaktualität durch Abgleich von Tabellenzeitstempeln und Aktualisierungsmustern mit einer Veraltungsskala. Identifiziert Zeitstempelspalten anhand gängiger ETL-Benennungsmuster (_loaded_at, _updated_at, created_at usw.) und fragt deren Maximalwerte ab, um das Alter zu bestimmen. Klassifiziert Daten in vier Aktualitätsstatus: Frisch (< 4 Stunden), Veraltet (4–24 Stunden), Stark veraltet (> 24 Stunden) oder Unbekannt (kein Zeitstempel gefunden). Stellt SQL-Vorlagen zur Überprüfung der letzten Aktualisierungszeit und der Zeilenanzahltrends der letzten Tage bereit, um...
official