A daily Airflow pipeline needs a boundary that tells the scheduler when its execution window begins. The start_date parameter marks that beginning; the schedule then determines the run times within the window. section 3.2 section 3.8
A start date works with schedule, optional end_date, and catchup. Together, these settings determine whether Airflow considers a DAG available, how often it runs, and whether it creates runs for past time points. section 3.2 section 3.3.5
Use the start date to reason about these scheduling behaviors:
- Pair it with a daily schedule to begin executions at a defined time, such as midnight UTC on January 1. section 3.3.1
- Add an end_date to limit the execution window; omit it when the DAG should continue indefinitely. section 3.3.1
- Enable catchup to create runs for missed time points between the start date and the present; otherwise, Airflow considers only future runs. section 3.2 section 3.3.1
- Use logical_date to identify the scheduled execution time when constructing date-specific queries or output filenames. section 3.3.5 section 3.3.1
Bounded daily schedule
with DAG( dag_id="02_daily_schedule", start_date=pendulum.datetime(year=2025, month=1, day=1), end_date=pendulum.datetime(year=2025, month=1, day=5), schedule=CronTriggerTimetable("0 0 * * *", timezone="UTC"), catchup=True, ): ... This configuration schedules daily runs at 00:00 UTC from the chosen start date through the end date, including past runs because catchup is enabled. section 3.3.1
Listing 3.2 Defining a daily schedule
from airflow.timetables.trigger import CronTriggerTimetable
with DAG(
dag_id="02_daily_schedule",
start_date=pendulum.datetime(year=2025, month=1, day=1), #1
end_date=pendulum.datetime(year=2025, month=1, day=5) #2
schedule=CronTriggerTimetable("0 0 * * *", timezone="UTC"), #3
...
):
Inspect the complete daily-schedule configuration, including start_date, end_date, and the cron-based schedule. section 3.3.1
