Lesson 5 · Scheduling & execution
Scheduling & data intervals
The one thing everyone gets wrong: when a scheduled run actually fires.
Your win: explain schedule, start_date, and
the data interval — and correctly answer "when does a daily DAG for Jan 1 run?" (the
question that catches people).
schedule + start_date
A DAG's schedule says how often it runs — a cron string
("0 18 * * *"), a preset, a timedelta, None
(manual), or a dataset trigger. Its start_date is the first logical date it's
scheduled from. Together they define the sequence of runs.1
(Airflow 3 uses schedule; Airflow 2 called it schedule_interval.)
Each run covers a data interval
Every DAG run is tied to a data interval — the time window of
data it should process (data_interval_start … data_interval_end).
The logical date is the start of that interval (it used
to be called the "execution date" — a misleading name).2
rules.yaml → the template's
schedule="{{schedule}}" — e.g. "00 18 * * *" (daily 18:00). The
generator defaults an omitted schedule to "0 0 * * *", and
schedule: None means manual-trigger only
(airflow/dags/rules.yaml · common-spark-job.py).
start_date is hard-coded datetime(2024, 1, 1) in the templates.
Astronomer — Scheduling in Airflow + DAG Runs
The clearest explanation of data intervals, logical date, and timetables. Pair with the official DAG Runs page.
→ astronomer.io/docs/learn — Scheduling
→ airflow.apache.org — DAG Runs
Check yourself (from memory)
Q1. A scheduled DAG run fires…
Q2. The logical date is the…
Q3. schedule=None means the DAG…
rules.yaml entries use schedule: None.
schedule (cron/preset/timedelta/None/dataset) + start_date
define the intervals; schedule=None = manual only.timetables (Airflow 2.2+) or dataset/asset-driven scheduling
generalise this? Ask me.