CronTriggerTimetable schedules Airflow DAG runs at cron-defined points in time rather than representing the schedule as data intervals. It requires a cron expression and time zone, such as midnight UTC each day. section 3.3.1 section 12.1.7
Schedule a bounded daily pipeline
from airflow.timetables.trigger import CronTriggerTimetable with DAG( dag_id="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 runs at 00:00 UTC from January 1 through January 5. Omitting end_date allows the DAG to continue indefinitely. Enabling catchup creates the past runs when their scheduled dates have already elapsed. section 3.3.1
Use CronTriggerTimetable deliberately in production workflows:
- Use @daily for the common midnight schedule; it is equivalent to 0 0 * * * with the UTC time zone. section 3.3.3
- Prefer the explicit timetable class over assigning a shorthand directly to schedule, because Airflow 2 and 3 apply such expressions differently by default. section 12.1.7
- Persist outputs under logical_date-specific paths instead of one shared file, preventing each run from overwriting earlier results. 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 DAG definition, including start and end dates and the explicit CronTriggerTimetable configuration. section 3.3.1
