Loading Academy Hub...
Master reliable dependency waiting in Airflow: Sensors, `mode='reschedule'` vs `mode='poke'` (preventing worker starvation), exponential sensor retry intervals, and complex trigger rules (`all_done`, `one_failed`).
[!NOTE] Sensors are specialized operators that wait for an external condition to become true (e.g., a file landing in S3, a table partition appearing, or a REST API endpoint returning 200).
poke vs reschedule (The Worker Starvation Trap)mode='poke' (Default): The sensor holds onto its worker slot for its entire duration, sleeping between check intervals. If a file takes 4 hours to arrive, that worker slot is locked for 4 hours doing nothing.
mode='reschedule': The sensor checks the condition; if false, it releases the worker slot and reschedules itself in the metadata database for the next check interval.
mode='reschedule' for any sensor waiting longer than 2 minutes!deferrable=True), Deadlock Prevention & Poolspoke Mode) Cause Worker Starvation: Standard polling sensors (poke mode) hold a full Worker process/pod hostage for hours sleeping between checks. Always set deferrable=True (e.g., S3KeySensor(..., deferrable=True), DatabricksRunNowOperator(..., deferrable=True), BigQueryInsertJobOperator(..., deferrable=True)) so the task yields immediately to the lightweight async Triggerer (asyncio), freeing 100% of Worker slots!mode="reschedule" rather than mode="poke" for waits exceeding 60 seconds so the worker slot returns to the pool between poke_interval checks.max_active_tis_per_dag) & exponential_backoff: Guard fragile downstream relational APIs or Snowflake staging tables using named Airflow Pools (slots=5) and retry_exponential_backoff=True + jitter so 100 failed tasks never DDoS your source ERP during recovery.Review the production code, company interview Q&As, incident traces, and comprehension quiz inside this lesson.
from airflow import DAG
from airflow.providers.amazon.aws.sensors.s3 import S3KeySensor
from airflow.operators.email import EmailOperator
from datetime import datetime, timedelta
with DAG('s3_file_waiter_dag', schedule='@hourly', start_date=datetime(2026, 1, 1), catchup=False) as dag:
# Safe Sensor: Releases worker slot between checks
wait_for_landing_file = S3KeySensor(
task_id='wait_for_transactions_s3',
bucket_name='enterprise-lakehouse-prod',
bucket_key='drop/transactions_{{ ds }}.parquet',
wildcard_match=False,
mode='reschedule', # CRITICAL: Releases worker slot
poke_interval=120, # Check every 2 minutes
timeout=3600, # Fail after 1 hour
exponential_backoff=True
)
# Alert Task: Executes only if sensor fails or times out
alert_on_sla_breach = EmailOperator(
task_id='alert_file_missing',
to='dataops@company.com',
subject='SLA Alert: Landing File Missing in S3',
html_content='The expected transactions file did not land within the 1-hour SLA.',
trigger_rule='one_failed' # Runs if upstream sensor fails
)
wait_for_landing_file >> alert_on_sla_breachAirflowPoolCapacityAlert: Pool 'default_pool' has 0 available slots. 16 tasks queued for > 1,200s.