Data Engineering/Orchestration & Quality
Orchestrating Pipelines with DAGs
Why pipelines are modeled as directed acyclic graphs, what tools like Airflow and Dagster actually coordinate, and the scheduling concepts that trip up beginners.
A real pipeline is rarely one script — it's a set of tasks with dependencies: extract before transform, transform before load, load before the downstream report refreshes. Orchestration tools exist to schedule, sequence, retry, and monitor exactly this kind of multi-step workflow.
Why a DAG (directed acyclic graph)
Pipelines are modeled as DAGs — directed, because dependencies flow one way (task B waits for task A), and acyclic, because a valid pipeline can never loop back on itself (that would mean a task depends on its own future output). Tools like Apache Airflow, Dagster, and Prefect let you define this graph in code and handle the mechanics of running it: scheduling, parallelizing independent branches, retrying failed tasks, and alerting when something breaks.
# A simplified Airflow-style DAG definition
with DAG("daily_orders", schedule="@daily") as dag:
extract = PythonOperator(task_id="extract_orders", python_callable=extract_orders)
transform = PythonOperator(task_id="transform_orders", python_callable=transform_orders)
load = PythonOperator(task_id="load_orders", python_callable=load_orders)
extract >> transform >> load # dependency orderConcepts that trip up beginners
- Schedule interval vs. execution date: a run 'for' yesterday often actually executes today
- Idempotency: re-running a task for the same input should produce the same result, not duplicate it
- Backfilling: running a DAG for past dates it missed or that predate its creation
- Sensors/triggers: tasks that wait for an external condition (a file landing, an upstream DAG finishing) rather than running on a fixed clock
Tip — Idempotency is the habit that saves you
Design every task so running it twice for the same input is safe — e.g. overwrite a partition rather than append to it. Pipelines fail and get retried constantly; non-idempotent tasks turn a retry into a data quality incident.
Orchestration is ultimately about making failure boring: when (not if) a task fails, the system should retry sensibly, alert the right person, and let you re-run just the affected part of the graph rather than the whole pipeline.