webtracking.org

Apache Airflow

The most widely deployed open-source workflow orchestrator, scheduling DAGs of Python-defined tasks across a huge provider ecosystem.

Pricing
free
Open source
Yes
Self-hostable
Yes

INTEGRATES: bigquery · snowflake · clickhouse · dbt

ALTERNATIVES: dagster

Airflow models work as DAGs of tasks written in Python, scheduled by interval or event, and executed by a fleet of workers. Its moat is the provider ecosystem — mature operators exist for practically every warehouse, cloud service, and data tool a tracking pipeline touches — plus a decade of operational lore, hiring pool, and managed offerings (Cloud Composer, MWAA, Astronomer). Airflow 3, released in 2025, modernized the foundations with DAG versioning, a rewritten UI, and a task execution interface that decouples workers from the metadata database; the 3.x line has kept moving since, adding asset partitioning in 3.2 and stateful tasks plus multi-language support in 3.3 (July 2026).

Operationally, a deployment is several cooperating services: a scheduler, a DAG processor that parses your DAG files and serializes them into the metadata database (usually PostgreSQL or MySQL), an API server that serves both the REST API and the UI, and — depending on executor — a pool of Celery or Kubernetes workers plus an optional triggerer that runs deferred tasks in an asyncio event loop. In Airflow 3 the DAG processor is deliberately separated from the scheduler so the scheduler never executes DAG-author code, and task code can no longer touch the metadata database directly — workers talk to the API server instead. That’s a real security and isolation win, but it also means custom operators written against Airflow 2 internals (direct DB sessions, airflow.models imports) need rework toward the airflow.sdk namespace.

Migrating from Airflow 2 is a project, not a version bump: the docs prescribe upgrading to 2.7+ first, linting DAGs with Ruff’s AIR rules (ruff check dags/ --select AIR301), installing the standard provider for operators that used to ship in core, and switching startup from webserver to api-server plus a standalone dag-processor. SubDAGs, the SequentialExecutor, SLAs (replaced by Deadline Alerts), and legacy context variables like execution_date are gone.

The classic gotchas are well documented by the project itself: top-level code in DAG files runs on every parse cycle, so expensive imports or API calls there quietly hammer the scheduler; tasks must be idempotent because retries and backfills re-run them; XCom is for small messages, not data — anything sizable belongs in object storage; and Variable.get() at top level hits the database where a Jinja template would not. The task-centric model is also worth internalizing: assets and data-aware scheduling have narrowed the gap, but asset-first lineage and partitioned backfills as core primitives remain the pitch of newer orchestrators. For steady ELT — load events, run dbt, kick off syncs — Airflow remains the safe, boring choice in the best sense.

Use it when you want the most battle-tested orchestrator, need operators for a sprawling set of systems, or your platform team already runs it. Look past it when you want asset-level lineage and partitioned backfills as built-ins, or a small team would rather not operate a scheduler, metadata database, DAG processor, and workers at all.

Visit site → Docs