
If you're building data pipelines with Airflow, this skill gives you production-ready DAG patterns that actually work in the real world. It covers TaskFlow API decorators for cleaner XCom passing, dynamic DAG generation from config files, proper branching with quality checks, and sensor patterns for external dependencies. The examples show concrete retry strategies, error handling, and testing approaches that prevent the common DAG antipatterns that break pipelines at 3am. Solid reference for both building new workflows and refactoring messy DAGs.
$ npx -y skills add wshobson/agents --skill airflow-dag-patterns --agent claude-codeInstalls into .claude/skills of the current project.
Production-ready patterns for Apache Airflow including DAG design, operators, sensors, testing, and deployment strategies.
| Principle | Description |
|---|---|
| Idempotent | Running twice produces same result |
| Atomic | Tasks succeed or fail completely |
| Incremental | Process only new/changed data |
| Observable | Logs, metrics, alerts at every step |
# Linear
task1 >> task2 >> task3
# Fan-out
task1 >> [task2, task3, task4]
# Fan-in
[task1, task2, task3] >> task4
# Complex
task1 >> task2 >> task4
task1 >> task3 >> task4
# dags/example_dag.py
from datetime import datetime, timedelta
from airflow import DAG
from airflow.operators.python import PythonOperator
from airflow.operators.empty import EmptyOperator
default_args = {
'owner': 'data-team',
'depends_on_past': False,
'email_on_failure': True,
'email_on_retry': False,
'retries': 3,
'retry_delay': timedelta(minutes=5),
'retry_exponential_backoff': True,
'max_retry_delay': timedelta(hours=1),
}
with DAG(
dag_id='example_etl',
default_args=default_args,
description='Example ETL pipeline',
schedule='0 6 * * *', # Daily at 6 AM
start_date=datetime(2024, 1, 1),
catchup=False,
tags=['etl', 'example'],
max_active_runs=1,
) as dag:
start = EmptyOperator(task_id='start')
def extract_data(**context):
execution_date = context['ds']
# Extract logic here
return {'records': 1000}
extract = PythonOperator(
task_id='extract',
python_callable=extract_data,
)
end = EmptyOperator(task_id='end')
start >> extract >> end
Detailed pattern documentation lives in references/details.md. Read that file when the navigation tier above is insufficient.
mode='reschedule' - For sensors, free up workersdepends_on_past=True - Creates bottlenecks{{ ds }} macrosSponsors