Apache Airflow
Apache Airflow is an open-source platform for programmatically authoring, scheduling, and monitoring workflows. Developed at Airbnb in 2014 and donated to the Apache Software Foundation, Airflow represents a particular theory about how data pipelines should be managed: not as implicit scripts that happen to run in sequence, but as explicit, version-controlled, observable directed acyclic graphs (DAGs) that encode dependencies as first-class citizens.
DAGs as Control Structures
At the core of Airflow is the DAG — a directed acyclic graph in which nodes are tasks and edges are dependencies. A task does not run until all of its upstream dependencies have succeeded. This is not merely scheduling; it is a control structure that makes the data pipeline's logic explicit and inspectable. Where traditional cron jobs hide dependencies in the timing of their schedules ('run job B at 3 AM because job A finishes at 2:45'), Airflow makes the dependency explicit: job B depends on job A.
This explicitness matters because data pipelines are systems, and systems fail in ways that implicit dependencies obscure. When a cron job fails, the downstream jobs that assumed its output will run anyway, producing garbage or crashing. Airflow's DAG structure prevents this by construction: a failed task blocks its downstream dependents, and the failure propagates visibly through the graph. The DAG is a fail-safe mechanism at the workflow level: it ensures that bad data does not flow downstream by halting the pipeline at the point of failure.
The Executor and the Worker
Airflow separates the definition of work (the DAG) from the execution of work (the executor and worker pool). The scheduler parses the DAG file, determines which tasks are ready to run based on their dependencies and schedules, and places them in a queue. The executor pulls tasks from the queue and dispatches them to workers. The worker executes the task and reports its status back.
This separation is a recognition that workflow management and task execution have different scaling characteristics. A scheduler needs to parse DAGs and evaluate dependencies — a metadata-intensive workload. A worker needs to run arbitrary Python code, SQL queries, or shell commands — a compute-intensive workload. By separating them, Airflow allows each to be scaled independently: more schedulers for complex DAGs, more workers for heavy tasks.
Sensors, Operators, and the Problem of Waiting
Airflow provides two fundamental abstractions for tasks: operators (tasks that do something) and sensors (tasks that wait for something). An operator might run a Python function, execute a SQL query, or transfer data between systems. A sensor polls an external condition — a file appearing in S3, a database row being updated, an API endpoint returning a specific status — and succeeds only when that condition is met.
Sensors are Airflow's solution to the problem of external dependencies: tasks that cannot begin until some condition outside the DAG is satisfied. But sensors are also a source of operational complexity. A sensor that polls too frequently wastes resources; a sensor that polls too infrequently adds latency. A sensor that waits for a condition that never arrives hangs indefinitely, consuming a worker slot. The design of sensors — their polling intervals, their timeout policies, their retry logic — is a microcosm of the larger problem of coordinating distributed systems: how do you wait for something without wasting resources, and how do you give up without missing something important?
Backfill and Idempotency
One of Airflow's most powerful features is backfill — the ability to run a DAG for historical date ranges. If a new data pipeline is deployed on March 1st but needs to process data from January 1st onward, Airflow can automatically schedule and execute the DAG for every date in that range. This is not merely a convenience; it is a design philosophy. Airflow assumes that tasks should be idempotent — that running the same task with the same inputs should produce the same outputs, regardless of when it runs.
Idempotency is a systems principle with deep roots. In distributed systems, idempotent operations can be retried safely without fear of double-counting or corruption. In Airflow, idempotency enables backfill, recovery from failure, and the reprocessing of data after code changes. A task that is not idempotent — one that appends to a table rather than overwriting it, or that sends an email notification — is a hazard in Airflow's model, because Airflow will run it multiple times without warning.
Airflow and the Data Infrastructure Stack
Airflow does not operate in isolation. It is one component of a larger data infrastructure ecosystem that includes storage systems (Apache Druid, Amazon S3, Google BigQuery), stream processors (Apache Kafka, Apache Flink), transformation engines (Apache Spark, dbt), and orchestration layers (Kubernetes, Docker). In this stack, Airflow plays the role of the conductor: it does not produce data, transform data, or store data; it coordinates the production, transformation, and storage of data by other systems.
This coordination role makes Airflow a critical point of failure. If Airflow's scheduler goes down, pipelines stop running. If Airflow's metadata database becomes corrupted, the history of what ran when and whether it succeeded is lost. If Airflow's worker pool is undersized, tasks queue indefinitely while downstream systems wait for data that never arrives. The reliability of the entire data infrastructure depends, in part, on the reliability of Airflow — a fact that is easy to forget because Airflow's job is to be invisible.
The Limits of DAG-Based Orchestration
Airflow's DAG model is powerful but not universal. It assumes that workflows can be represented as static, acyclic graphs with clearly defined tasks and dependencies. This assumption breaks down in several common scenarios. Dynamic workflows — where the set of tasks depends on runtime data — require workarounds like the TaskFlow API or dynamic task mapping, which stretch the DAG abstraction. Cyclic dependencies — where task A depends on task B and task B depends on task A — cannot be represented in a DAG at all. Event-driven workflows — where tasks trigger in response to external events rather than on a schedule — are awkward in Airflow's batch-oriented model.
These limitations are not flaws in Airflow's implementation. They are consequences of its foundational abstraction. The DAG is a model, and like all models, it simplifies some aspects of reality while distorting others. The question for practitioners is not whether Airflow is good or bad, but whether their workflows fit the DAG model well enough that the benefits of explicit dependencies and visible failure propagation outweigh the costs of working around the model's limitations.
The lesson of Airflow is that workflow orchestration is not a solved problem dressed in Python syntax. It is an active area of systems design where the choice of abstraction — DAG, event stream, state machine — determines what kinds of failure modes are visible, what kinds of dependencies are expressible, and what kinds of optimization are possible. Airflow chose the DAG, and that choice has made it the dominant orchestrator for batch data pipelines. But the DAG is not the final word. It is one node in a larger design space that includes stream processing, serverless functions, and reactive systems — and the boundaries between these paradigms are where the next generation of orchestration will emerge.