[{"data":1,"prerenderedAt":1624},["ShallowReactive",2],{"guide-airflow-cron-scheduling":3},{"id":4,"title":5,"body":6,"date":1616,"description":1617,"extension":1618,"meta":1619,"navigation":278,"path":1620,"readingTime":306,"seo":1621,"stem":1622,"__hash__":1623},"guides\u002Fguides\u002Fairflow-cron-scheduling.md","Apache Airflow Cron Scheduling: Complete Configuration Guide",{"type":7,"value":8,"toc":1574},"minimark",[9,14,18,21,25,30,142,146,152,162,165,216,220,224,230,259,309,313,316,372,376,379,523,527,531,562,566,597,601,632,636,667,671,702,706,737,741,745,752,768,823,827,911,921,951,955,959,1041,1045,1091,1095,1099,1109,1173,1177,1188,1192,1203,1207,1211,1264,1268,1325,1329,1359,1363,1366,1400,1404,1461,1465,1556,1560,1570],[10,11,13],"h2",{"id":12},"introduction","Introduction",[15,16,17],"p",{},"Apache Airflow uses cron expressions for scheduling DAGs (Directed Acyclic Graphs), but its scheduling semantics differ significantly from system cron. Understanding these differences is crucial to avoid common pitfalls that cause DAGs to run at unexpected times—or not at all.",[15,19,20],{},"This guide covers Airflow's scheduling system, how it differs from system cron, common scheduling patterns, and the traps that catch even experienced users.",[10,22,24],{"id":23},"airflow-scheduling-vs-system-cron","Airflow Scheduling vs System Cron",[26,27,29],"h3",{"id":28},"key-differences","Key Differences",[31,32,33,49],"table",{},[34,35,36],"thead",{},[37,38,39,43,46],"tr",{},[40,41,42],"th",{},"Aspect",[40,44,45],{},"System Cron",[40,47,48],{},"Apache Airflow",[50,51,52,71,84,96,109,122],"tbody",{},[37,53,54,61,64],{},[55,56,57],"td",{},[58,59,60],"strong",{},"Execution Model",[55,62,63],{},"Runs at the specified time",[55,65,66,67,70],{},"Runs ",[58,68,69],{},"after"," the scheduled period ends",[37,72,73,78,81],{},[55,74,75],{},[58,76,77],{},"start_date",[55,79,80],{},"Not applicable",[55,82,83],{},"Determines the first scheduled period",[37,85,86,91,93],{},[55,87,88],{},[58,89,90],{},"catchup",[55,92,80],{},[55,94,95],{},"Replays missed runs by default",[37,97,98,103,106],{},[55,99,100],{},[58,101,102],{},"Timezone",[55,104,105],{},"System timezone (usually)",[55,107,108],{},"Per-DAG timezone support",[37,110,111,116,119],{},[55,112,113],{},[58,114,115],{},"Skip Missed",[55,117,118],{},"Missed jobs are lost",[55,120,121],{},"Can catch up or skip (catchup=True\u002FFalse)",[37,123,124,129,132],{},[55,125,126],{},[58,127,128],{},"Schedule Definition",[55,130,131],{},"Crontab file",[55,133,134,138,139],{},[135,136,137],"code",{},"schedule_interval"," parameter or ",[135,140,141],{},"Timetable",[26,143,145],{"id":144},"the-after-period-concept","The \"After Period\" Concept",[15,147,148,149],{},"The most confusing aspect of Airflow scheduling: ",[58,150,151],{},"Airflow schedules a DAG run AFTER the scheduled period ends, not AT the cron time.",[153,154,159],"pre",{"className":155,"code":157,"language":158},[156],"language-text","Cron: 0 0 * * * (midnight)\nSystem cron: Runs at 00:00:00\nAirflow: Runs at 00:00:00 to process the PREVIOUS day's data\n","text",[135,160,157],{"__ignoreMap":161},"",[15,163,164],{},"Example:",[153,166,170],{"className":167,"code":168,"language":169,"meta":161,"style":161},"language-python shiki shiki-themes github-light github-dark","# This DAG's first run will be scheduled for 2024-01-02 00:00:00\n# That run processes data for 2024-01-01\ndag = DAG(\n    'daily_etl',\n    start_date=datetime(2024, 1, 1),\n    schedule_interval='0 0 * * *',  # Midnight\n)\n","python",[135,171,172,180,186,192,198,204,210],{"__ignoreMap":161},[173,174,177],"span",{"class":175,"line":176},"line",1,[173,178,179],{},"# This DAG's first run will be scheduled for 2024-01-02 00:00:00\n",[173,181,183],{"class":175,"line":182},2,[173,184,185],{},"# That run processes data for 2024-01-01\n",[173,187,189],{"class":175,"line":188},3,[173,190,191],{},"dag = DAG(\n",[173,193,195],{"class":175,"line":194},4,[173,196,197],{},"    'daily_etl',\n",[173,199,201],{"class":175,"line":200},5,[173,202,203],{},"    start_date=datetime(2024, 1, 1),\n",[173,205,207],{"class":175,"line":206},6,[173,208,209],{},"    schedule_interval='0 0 * * *',  # Midnight\n",[173,211,213],{"class":175,"line":212},7,[173,214,215],{},")\n",[10,217,219],{"id":218},"schedule_interval-vs-timetable","schedule_interval vs Timetable",[26,221,223],{"id":222},"schedule_interval-traditional-approach","schedule_interval (Traditional Approach)",[15,225,226,227,229],{},"The ",[135,228,137],{}," parameter accepts:",[231,232,233,240,253],"ul",{},[234,235,236,237],"li",{},"Cron expressions as strings: ",[135,238,239],{},"'0 0 * * *'",[234,241,242,243,246,247,246,250],{},"Presets: ",[135,244,245],{},"'@daily'",", ",[135,248,249],{},"'@hourly'",[135,251,252],{},"'@weekly'",[234,254,255,256],{},"timedelta objects: ",[135,257,258],{},"timedelta(hours=6)",[153,260,262],{"className":167,"code":261,"language":169,"meta":161,"style":161},"from airflow import DAG\nfrom datetime import datetime, timedelta\n\ndag = DAG(\n    'example_dag',\n    start_date=datetime(2024, 1, 1),\n    schedule_interval='0 *\u002F6 * * *',  # Every 6 hours\n    catchup=False,\n)\n",[135,263,264,269,274,280,284,289,293,298,304],{"__ignoreMap":161},[173,265,266],{"class":175,"line":176},[173,267,268],{},"from airflow import DAG\n",[173,270,271],{"class":175,"line":182},[173,272,273],{},"from datetime import datetime, timedelta\n",[173,275,276],{"class":175,"line":188},[173,277,279],{"emptyLinePlaceholder":278},true,"\n",[173,281,282],{"class":175,"line":194},[173,283,191],{},[173,285,286],{"class":175,"line":200},[173,287,288],{},"    'example_dag',\n",[173,290,291],{"class":175,"line":206},[173,292,203],{},[173,294,295],{"class":175,"line":212},[173,296,297],{},"    schedule_interval='0 *\u002F6 * * *',  # Every 6 hours\n",[173,299,301],{"class":175,"line":300},8,[173,302,303],{},"    catchup=False,\n",[173,305,307],{"class":175,"line":306},9,[173,308,215],{},[26,310,312],{"id":311},"timetable-modern-approach-airflow-22","Timetable (Modern Approach, Airflow 2.2+)",[15,314,315],{},"Timetables provide more control over scheduling logic, especially for complex business calendars:",[153,317,319],{"className":167,"code":318,"language":169,"meta":161,"style":161},"from airflow.timetables.trigger import CronTriggerTimetable\n\ndag = DAG(\n    'example_dag',\n    start_date=datetime(2024, 1, 1),\n    # More explicit: runs at midnight in UTC\n    schedule=Timetable(\n        cron=CronTriggerTimetable(\"0 0 * * *\", timezone=\"UTC\"),\n    ),\n    catchup=False,\n)\n",[135,320,321,326,330,334,338,342,347,352,357,362,367],{"__ignoreMap":161},[173,322,323],{"class":175,"line":176},[173,324,325],{},"from airflow.timetables.trigger import CronTriggerTimetable\n",[173,327,328],{"class":175,"line":182},[173,329,279],{"emptyLinePlaceholder":278},[173,331,332],{"class":175,"line":188},[173,333,191],{},[173,335,336],{"class":175,"line":194},[173,337,288],{},[173,339,340],{"class":175,"line":200},[173,341,203],{},[173,343,344],{"class":175,"line":206},[173,345,346],{},"    # More explicit: runs at midnight in UTC\n",[173,348,349],{"class":175,"line":212},[173,350,351],{},"    schedule=Timetable(\n",[173,353,354],{"class":175,"line":300},[173,355,356],{},"        cron=CronTriggerTimetable(\"0 0 * * *\", timezone=\"UTC\"),\n",[173,358,359],{"class":175,"line":306},[173,360,361],{},"    ),\n",[173,363,365],{"class":175,"line":364},10,[173,366,303],{},[173,368,370],{"class":175,"line":369},11,[173,371,215],{},[26,373,375],{"id":374},"custom-timetable-example","Custom Timetable Example",[15,377,378],{},"For business-day-only scheduling (skip weekends):",[153,380,382],{"className":167,"code":381,"language":169,"meta":161,"style":161},"from airflow.timetables.base import Timetable\nfrom datetime import datetime\nimport pendulum\n\nclass BusinessDayTimetable(Timetable):\n    def next_dagrun_info(self, last_automated_data_interval, restriction):\n        # Calculate next business day\n        if last_automated_data_interval is None:\n            next_start = datetime(2024, 1, 1, tzinfo=pendulum.UTC)\n        else:\n            next_start = last_automated_data_interval.end + timedelta(days=1)\n            # Skip weekends\n            while next_start.weekday() >= 5:  # 5=Saturday, 6=Sunday\n                next_start += timedelta(days=1)\n        \n        return DagRunInfo(\n            run_after=next_start,\n            data_interval=(next_start, next_start + timedelta(days=1))\n        )\n\ndag = DAG(\n    'business_day_dag',\n    start_date=datetime(2024, 1, 1),\n    schedule=BusinessDayTimetable(),\n    catchup=False,\n)\n",[135,383,384,389,394,399,403,408,413,418,423,428,433,438,444,450,456,462,468,474,480,486,491,496,502,507,513,518],{"__ignoreMap":161},[173,385,386],{"class":175,"line":176},[173,387,388],{},"from airflow.timetables.base import Timetable\n",[173,390,391],{"class":175,"line":182},[173,392,393],{},"from datetime import datetime\n",[173,395,396],{"class":175,"line":188},[173,397,398],{},"import pendulum\n",[173,400,401],{"class":175,"line":194},[173,402,279],{"emptyLinePlaceholder":278},[173,404,405],{"class":175,"line":200},[173,406,407],{},"class BusinessDayTimetable(Timetable):\n",[173,409,410],{"class":175,"line":206},[173,411,412],{},"    def next_dagrun_info(self, last_automated_data_interval, restriction):\n",[173,414,415],{"class":175,"line":212},[173,416,417],{},"        # Calculate next business day\n",[173,419,420],{"class":175,"line":300},[173,421,422],{},"        if last_automated_data_interval is None:\n",[173,424,425],{"class":175,"line":306},[173,426,427],{},"            next_start = datetime(2024, 1, 1, tzinfo=pendulum.UTC)\n",[173,429,430],{"class":175,"line":364},[173,431,432],{},"        else:\n",[173,434,435],{"class":175,"line":369},[173,436,437],{},"            next_start = last_automated_data_interval.end + timedelta(days=1)\n",[173,439,441],{"class":175,"line":440},12,[173,442,443],{},"            # Skip weekends\n",[173,445,447],{"class":175,"line":446},13,[173,448,449],{},"            while next_start.weekday() >= 5:  # 5=Saturday, 6=Sunday\n",[173,451,453],{"class":175,"line":452},14,[173,454,455],{},"                next_start += timedelta(days=1)\n",[173,457,459],{"class":175,"line":458},15,[173,460,461],{},"        \n",[173,463,465],{"class":175,"line":464},16,[173,466,467],{},"        return DagRunInfo(\n",[173,469,471],{"class":175,"line":470},17,[173,472,473],{},"            run_after=next_start,\n",[173,475,477],{"class":175,"line":476},18,[173,478,479],{},"            data_interval=(next_start, next_start + timedelta(days=1))\n",[173,481,483],{"class":175,"line":482},19,[173,484,485],{},"        )\n",[173,487,489],{"class":175,"line":488},20,[173,490,279],{"emptyLinePlaceholder":278},[173,492,494],{"class":175,"line":493},21,[173,495,191],{},[173,497,499],{"class":175,"line":498},22,[173,500,501],{},"    'business_day_dag',\n",[173,503,505],{"class":175,"line":504},23,[173,506,203],{},[173,508,510],{"class":175,"line":509},24,[173,511,512],{},"    schedule=BusinessDayTimetable(),\n",[173,514,516],{"class":175,"line":515},25,[173,517,303],{},[173,519,521],{"class":175,"line":520},26,[173,522,215],{},[10,524,526],{"id":525},"common-scheduling-patterns","Common Scheduling Patterns",[26,528,530],{"id":529},"daily-at-midnight-utc","Daily at Midnight (UTC)",[153,532,534],{"className":167,"code":533,"language":169,"meta":161,"style":161},"dag = DAG(\n    'daily_midnight',\n    start_date=datetime(2024, 1, 1),\n    schedule_interval='0 0 * * *',\n    catchup=False,\n)\n",[135,535,536,540,545,549,554,558],{"__ignoreMap":161},[173,537,538],{"class":175,"line":176},[173,539,191],{},[173,541,542],{"class":175,"line":182},[173,543,544],{},"    'daily_midnight',\n",[173,546,547],{"class":175,"line":188},[173,548,203],{},[173,550,551],{"class":175,"line":194},[173,552,553],{},"    schedule_interval='0 0 * * *',\n",[173,555,556],{"class":175,"line":200},[173,557,303],{},[173,559,560],{"class":175,"line":206},[173,561,215],{},[26,563,565],{"id":564},"every-6-hours","Every 6 Hours",[153,567,569],{"className":167,"code":568,"language":169,"meta":161,"style":161},"dag = DAG(\n    'every_6_hours',\n    start_date=datetime(2024, 1, 1),\n    schedule_interval='0 *\u002F6 * * *',\n    catchup=False,\n)\n",[135,570,571,575,580,584,589,593],{"__ignoreMap":161},[173,572,573],{"class":175,"line":176},[173,574,191],{},[173,576,577],{"class":175,"line":182},[173,578,579],{},"    'every_6_hours',\n",[173,581,582],{"class":175,"line":188},[173,583,203],{},[173,585,586],{"class":175,"line":194},[173,587,588],{},"    schedule_interval='0 *\u002F6 * * *',\n",[173,590,591],{"class":175,"line":200},[173,592,303],{},[173,594,595],{"class":175,"line":206},[173,596,215],{},[26,598,600],{"id":599},"weekly-on-monday-morning","Weekly on Monday Morning",[153,602,604],{"className":167,"code":603,"language":169,"meta":161,"style":161},"dag = DAG(\n    'weekly_monday',\n    start_date=datetime(2024, 1, 1),\n    schedule_interval='0 8 * * 1',  # 8 AM every Monday\n    catchup=False,\n)\n",[135,605,606,610,615,619,624,628],{"__ignoreMap":161},[173,607,608],{"class":175,"line":176},[173,609,191],{},[173,611,612],{"class":175,"line":182},[173,613,614],{},"    'weekly_monday',\n",[173,616,617],{"class":175,"line":188},[173,618,203],{},[173,620,621],{"class":175,"line":194},[173,622,623],{},"    schedule_interval='0 8 * * 1',  # 8 AM every Monday\n",[173,625,626],{"class":175,"line":200},[173,627,303],{},[173,629,630],{"class":175,"line":206},[173,631,215],{},[26,633,635],{"id":634},"first-day-of-month","First Day of Month",[153,637,639],{"className":167,"code":638,"language":169,"meta":161,"style":161},"dag = DAG(\n    'monthly_report',\n    start_date=datetime(2024, 1, 1),\n    schedule_interval='0 0 1 * *',  # Midnight on the 1st\n    catchup=False,\n)\n",[135,640,641,645,650,654,659,663],{"__ignoreMap":161},[173,642,643],{"class":175,"line":176},[173,644,191],{},[173,646,647],{"class":175,"line":182},[173,648,649],{},"    'monthly_report',\n",[173,651,652],{"class":175,"line":188},[173,653,203],{},[173,655,656],{"class":175,"line":194},[173,657,658],{},"    schedule_interval='0 0 1 * *',  # Midnight on the 1st\n",[173,660,661],{"class":175,"line":200},[173,662,303],{},[173,664,665],{"class":175,"line":206},[173,666,215],{},[26,668,670],{"id":669},"every-15-minutes","Every 15 Minutes",[153,672,674],{"className":167,"code":673,"language":169,"meta":161,"style":161},"dag = DAG(\n    'frequent_check',\n    start_date=datetime(2024, 1, 1),\n    schedule_interval='*\u002F15 * * * *',\n    catchup=False,\n)\n",[135,675,676,680,685,689,694,698],{"__ignoreMap":161},[173,677,678],{"class":175,"line":176},[173,679,191],{},[173,681,682],{"class":175,"line":182},[173,683,684],{},"    'frequent_check',\n",[173,686,687],{"class":175,"line":188},[173,688,203],{},[173,690,691],{"class":175,"line":194},[173,692,693],{},"    schedule_interval='*\u002F15 * * * *',\n",[173,695,696],{"class":175,"line":200},[173,697,303],{},[173,699,700],{"class":175,"line":206},[173,701,215],{},[26,703,705],{"id":704},"business-hours-only-9-am-5-pm-mon-fri","Business Hours Only (9 AM - 5 PM, Mon-Fri)",[153,707,709],{"className":167,"code":708,"language":169,"meta":161,"style":161},"dag = DAG(\n    'business_hours',\n    start_date=datetime(2024, 1, 1),\n    schedule_interval='0 9-17 * * 1-5',  # 9 AM to 5 PM, Mon-Fri\n    catchup=False,\n)\n",[135,710,711,715,720,724,729,733],{"__ignoreMap":161},[173,712,713],{"class":175,"line":176},[173,714,191],{},[173,716,717],{"class":175,"line":182},[173,718,719],{},"    'business_hours',\n",[173,721,722],{"class":175,"line":188},[173,723,203],{},[173,725,726],{"class":175,"line":194},[173,727,728],{},"    schedule_interval='0 9-17 * * 1-5',  # 9 AM to 5 PM, Mon-Fri\n",[173,730,731],{"class":175,"line":200},[173,732,303],{},[173,734,735],{"class":175,"line":206},[173,736,215],{},[10,738,740],{"id":739},"the-start_date-trap","The start_date Trap",[26,742,744],{"id":743},"misconception-start_date-is-when-the-dag-starts-running","Misconception: start_date is When the DAG Starts Running",[15,746,747,748,751],{},"Many users think ",[135,749,750],{},"start_date=datetime(2024, 1, 1)"," means \"start running on January 1st.\"",[15,753,754,757,758,760,761,764,765,767],{},[58,755,756],{},"Reality",": ",[135,759,77],{}," defines the beginning of the ",[58,762,763],{},"first scheduled period",". The DAG runs ",[58,766,69],{}," that period ends.",[153,769,771],{"className":167,"code":770,"language":169,"meta":161,"style":161},"# WRONG mental model:\n# \"This runs starting January 1st at midnight\"\ndag = DAG(\n    'daily',\n    start_date=datetime(2024, 1, 1),\n    schedule_interval='0 0 * * *',\n)\n\n# CORRECT mental model:\n# \"The first scheduled period is January 1st (00:00-24:00)\"\n# \"The DAG runs at January 2nd 00:00 to process January 1st's data\"\n",[135,772,773,778,783,787,792,796,800,804,808,813,818],{"__ignoreMap":161},[173,774,775],{"class":175,"line":176},[173,776,777],{},"# WRONG mental model:\n",[173,779,780],{"class":175,"line":182},[173,781,782],{},"# \"This runs starting January 1st at midnight\"\n",[173,784,785],{"class":175,"line":188},[173,786,191],{},[173,788,789],{"class":175,"line":194},[173,790,791],{},"    'daily',\n",[173,793,794],{"class":175,"line":200},[173,795,203],{},[173,797,798],{"class":175,"line":206},[173,799,553],{},[173,801,802],{"class":175,"line":212},[173,803,215],{},[173,805,806],{"class":175,"line":300},[173,807,279],{"emptyLinePlaceholder":278},[173,809,810],{"class":175,"line":306},[173,811,812],{},"# CORRECT mental model:\n",[173,814,815],{"class":175,"line":364},[173,816,817],{},"# \"The first scheduled period is January 1st (00:00-24:00)\"\n",[173,819,820],{"class":175,"line":369},[173,821,822],{},"# \"The DAG runs at January 2nd 00:00 to process January 1st's data\"\n",[26,824,826],{"id":825},"the-start_date-schedule_interval-interaction","The start_date + schedule_interval Interaction",[153,828,830],{"className":167,"code":829,"language":169,"meta":161,"style":161},"from datetime import datetime\n\n# Scenario: Today is 2024-01-10\n# start_date is in the past\ndag = DAG(\n    'example',\n    start_date=datetime(2024, 1, 1),  # 9 days ago\n    schedule_interval='0 0 * * *',\n    catchup=True,  # Default is True!\n)\n\n# With catchup=True, Airflow will schedule runs for:\n# 2024-01-02 00:00 (processes Jan 1st data)\n# 2024-01-03 00:00 (processes Jan 2nd data)\n# ...\n# 2024-01-10 00:00 (processes Jan 9th data)\n# That's 9 backfill runs!\n",[135,831,832,836,840,845,850,854,859,864,868,873,877,881,886,891,896,901,906],{"__ignoreMap":161},[173,833,834],{"class":175,"line":176},[173,835,393],{},[173,837,838],{"class":175,"line":182},[173,839,279],{"emptyLinePlaceholder":278},[173,841,842],{"class":175,"line":188},[173,843,844],{},"# Scenario: Today is 2024-01-10\n",[173,846,847],{"class":175,"line":194},[173,848,849],{},"# start_date is in the past\n",[173,851,852],{"class":175,"line":200},[173,853,191],{},[173,855,856],{"class":175,"line":206},[173,857,858],{},"    'example',\n",[173,860,861],{"class":175,"line":212},[173,862,863],{},"    start_date=datetime(2024, 1, 1),  # 9 days ago\n",[173,865,866],{"class":175,"line":300},[173,867,553],{},[173,869,870],{"class":175,"line":306},[173,871,872],{},"    catchup=True,  # Default is True!\n",[173,874,875],{"class":175,"line":364},[173,876,215],{},[173,878,879],{"class":175,"line":369},[173,880,279],{"emptyLinePlaceholder":278},[173,882,883],{"class":175,"line":440},[173,884,885],{},"# With catchup=True, Airflow will schedule runs for:\n",[173,887,888],{"class":175,"line":446},[173,889,890],{},"# 2024-01-02 00:00 (processes Jan 1st data)\n",[173,892,893],{"class":175,"line":452},[173,894,895],{},"# 2024-01-03 00:00 (processes Jan 2nd data)\n",[173,897,898],{"class":175,"line":458},[173,899,900],{},"# ...\n",[173,902,903],{"class":175,"line":464},[173,904,905],{},"# 2024-01-10 00:00 (processes Jan 9th data)\n",[173,907,908],{"class":175,"line":470},[173,909,910],{},"# That's 9 backfill runs!\n",[15,912,913,916,917,920],{},[58,914,915],{},"The fix",": Set ",[135,918,919],{},"catchup=False"," unless you want backfill:",[153,922,924],{"className":167,"code":923,"language":169,"meta":161,"style":161},"dag = DAG(\n    'example',\n    start_date=datetime(2024, 1, 1),\n    schedule_interval='0 0 * * *',\n    catchup=False,  # Only schedule the most recent period\n)\n",[135,925,926,930,934,938,942,947],{"__ignoreMap":161},[173,927,928],{"class":175,"line":176},[173,929,191],{},[173,931,932],{"class":175,"line":182},[173,933,858],{},[173,935,936],{"class":175,"line":188},[173,937,203],{},[173,939,940],{"class":175,"line":194},[173,941,553],{},[173,943,944],{"class":175,"line":200},[173,945,946],{},"    catchup=False,  # Only schedule the most recent period\n",[173,948,949],{"class":175,"line":206},[173,950,215],{},[10,952,954],{"id":953},"timezone-handling","Timezone Handling",[26,956,958],{"id":957},"always-use-utc-in-start_date","Always Use UTC in start_date",[153,960,962],{"className":167,"code":961,"language":169,"meta":161,"style":161},"# GOOD: Use UTC\nfrom datetime import datetime\nimport pendulum\n\ndag = DAG(\n    'timezone_example',\n    start_date=datetime(2024, 1, 1, tzinfo=pendulum.UTC),\n    schedule_interval='0 0 * * *',\n    catchup=False,\n)\n\n# BETTER: Use pendulum for clarity\ndag = DAG(\n    'timezone_example',\n    start_date=pendulum.datetime(2024, 1, 1, tz=\"UTC\"),\n    schedule_interval='0 0 * * *',\n    catchup=False,\n)\n",[135,963,964,969,973,977,981,985,990,995,999,1003,1007,1011,1016,1020,1024,1029,1033,1037],{"__ignoreMap":161},[173,965,966],{"class":175,"line":176},[173,967,968],{},"# GOOD: Use UTC\n",[173,970,971],{"class":175,"line":182},[173,972,393],{},[173,974,975],{"class":175,"line":188},[173,976,398],{},[173,978,979],{"class":175,"line":194},[173,980,279],{"emptyLinePlaceholder":278},[173,982,983],{"class":175,"line":200},[173,984,191],{},[173,986,987],{"class":175,"line":206},[173,988,989],{},"    'timezone_example',\n",[173,991,992],{"class":175,"line":212},[173,993,994],{},"    start_date=datetime(2024, 1, 1, tzinfo=pendulum.UTC),\n",[173,996,997],{"class":175,"line":300},[173,998,553],{},[173,1000,1001],{"class":175,"line":306},[173,1002,303],{},[173,1004,1005],{"class":175,"line":364},[173,1006,215],{},[173,1008,1009],{"class":175,"line":369},[173,1010,279],{"emptyLinePlaceholder":278},[173,1012,1013],{"class":175,"line":440},[173,1014,1015],{},"# BETTER: Use pendulum for clarity\n",[173,1017,1018],{"class":175,"line":446},[173,1019,191],{},[173,1021,1022],{"class":175,"line":452},[173,1023,989],{},[173,1025,1026],{"class":175,"line":458},[173,1027,1028],{},"    start_date=pendulum.datetime(2024, 1, 1, tz=\"UTC\"),\n",[173,1030,1031],{"class":175,"line":464},[173,1032,553],{},[173,1034,1035],{"class":175,"line":470},[173,1036,303],{},[173,1038,1039],{"class":175,"line":476},[173,1040,215],{},[26,1042,1044],{"id":1043},"scheduling-in-a-specific-timezone","Scheduling in a Specific Timezone",[153,1046,1048],{"className":167,"code":1047,"language":169,"meta":161,"style":161},"dag = DAG(\n    'tokyo_daily',\n    start_date=pendulum.datetime(2024, 1, 1, tz=\"Asia\u002FTokyo\"),\n    schedule_interval='0 9 * * *',  # 9 AM Tokyo time\n    catchup=False,\n)\n\n# The cron expression '0 9 * * *' is interpreted in the DAG's timezone\n# So this runs at 9 AM Asia\u002FTokyo, not 9 AM UTC\n",[135,1049,1050,1054,1059,1064,1069,1073,1077,1081,1086],{"__ignoreMap":161},[173,1051,1052],{"class":175,"line":176},[173,1053,191],{},[173,1055,1056],{"class":175,"line":182},[173,1057,1058],{},"    'tokyo_daily',\n",[173,1060,1061],{"class":175,"line":188},[173,1062,1063],{},"    start_date=pendulum.datetime(2024, 1, 1, tz=\"Asia\u002FTokyo\"),\n",[173,1065,1066],{"class":175,"line":194},[173,1067,1068],{},"    schedule_interval='0 9 * * *',  # 9 AM Tokyo time\n",[173,1070,1071],{"class":175,"line":200},[173,1072,303],{},[173,1074,1075],{"class":175,"line":206},[173,1076,215],{},[173,1078,1079],{"class":175,"line":212},[173,1080,279],{"emptyLinePlaceholder":278},[173,1082,1083],{"class":175,"line":300},[173,1084,1085],{},"# The cron expression '0 9 * * *' is interpreted in the DAG's timezone\n",[173,1087,1088],{"class":175,"line":306},[173,1089,1090],{},"# So this runs at 9 AM Asia\u002FTokyo, not 9 AM UTC\n",[10,1092,1094],{"id":1093},"catchup-the-silent-dag-runner","catchup: The Silent DAG Runner",[26,1096,1098],{"id":1097},"what-catchup-does","What catchup Does",[15,1100,1101,1102,1105,1106,1108],{},"When ",[135,1103,1104],{},"catchup=True"," (the default), Airflow will schedule all missed runs between ",[135,1107,77],{}," and the current date.",[153,1110,1112],{"className":167,"code":1111,"language":169,"meta":161,"style":161},"# Today is 2024-01-10\ndag = DAG(\n    'catchup_example',\n    start_date=datetime(2024, 1, 1),  # 9 days ago\n    schedule_interval='0 0 * * *',\n    catchup=True,  # This is the default!\n)\n\n# Airflow will create 9 DAG runs immediately:\n# - 2024-01-02 00:00 (for Jan 1st data)\n# - 2024-01-03 00:00 (for Jan 2nd data)\n# ...\n# - 2024-01-10 00:00 (for Jan 9th data)\n",[135,1113,1114,1119,1123,1128,1132,1136,1141,1145,1149,1154,1159,1164,1168],{"__ignoreMap":161},[173,1115,1116],{"class":175,"line":176},[173,1117,1118],{},"# Today is 2024-01-10\n",[173,1120,1121],{"class":175,"line":182},[173,1122,191],{},[173,1124,1125],{"class":175,"line":188},[173,1126,1127],{},"    'catchup_example',\n",[173,1129,1130],{"class":175,"line":194},[173,1131,863],{},[173,1133,1134],{"class":175,"line":200},[173,1135,553],{},[173,1137,1138],{"class":175,"line":206},[173,1139,1140],{},"    catchup=True,  # This is the default!\n",[173,1142,1143],{"class":175,"line":212},[173,1144,215],{},[173,1146,1147],{"class":175,"line":300},[173,1148,279],{"emptyLinePlaceholder":278},[173,1150,1151],{"class":175,"line":306},[173,1152,1153],{},"# Airflow will create 9 DAG runs immediately:\n",[173,1155,1156],{"class":175,"line":364},[173,1157,1158],{},"# - 2024-01-02 00:00 (for Jan 1st data)\n",[173,1160,1161],{"class":175,"line":369},[173,1162,1163],{},"# - 2024-01-03 00:00 (for Jan 2nd data)\n",[173,1165,1166],{"class":175,"line":440},[173,1167,900],{},[173,1169,1170],{"class":175,"line":446},[173,1171,1172],{},"# - 2024-01-10 00:00 (for Jan 9th data)\n",[26,1174,1176],{"id":1175},"when-to-use-catchuptrue","When to Use catchup=True",[231,1178,1179,1182,1185],{},[234,1180,1181],{},"Initial backfill of historical data",[234,1183,1184],{},"Re-processing after fixing a bug",[234,1186,1187],{},"Data pipelines where historical data is needed",[26,1189,1191],{"id":1190},"when-to-use-catchupfalse","When to Use catchup=False",[231,1193,1194,1197,1200],{},[234,1195,1196],{},"Live production pipelines (only process current data)",[234,1198,1199],{},"Resource-intensive DAGs (avoid sudden load spike)",[234,1201,1202],{},"DAGs with external dependencies that only exist for recent data",[10,1204,1206],{"id":1205},"debugging-scheduling-issues","Debugging Scheduling Issues",[26,1208,1210],{"id":1209},"_1-check-when-the-next-run-is-scheduled","1. Check When the Next Run Is Scheduled",[153,1212,1216],{"className":1213,"code":1214,"language":1215,"meta":161,"style":161},"language-bash shiki shiki-themes github-light github-dark","# Using CLI\nairflow dags show \u003Cdag_id> --tree\n\n# Or in the UI: Browse -> DAGs -> [Your DAG] -> \"Next Run\" column\n","bash",[135,1217,1218,1224,1255,1259],{"__ignoreMap":161},[173,1219,1220],{"class":175,"line":176},[173,1221,1223],{"class":1222},"sJ8bj","# Using CLI\n",[173,1225,1226,1230,1234,1237,1241,1244,1248,1251],{"class":175,"line":182},[173,1227,1229],{"class":1228},"sScJk","airflow",[173,1231,1233],{"class":1232},"sZZnC"," dags",[173,1235,1236],{"class":1232}," show",[173,1238,1240],{"class":1239},"szBVR"," \u003C",[173,1242,1243],{"class":1232},"dag_i",[173,1245,1247],{"class":1246},"sVt8B","d",[173,1249,1250],{"class":1239},">",[173,1252,1254],{"class":1253},"sj4cs"," --tree\n",[173,1256,1257],{"class":175,"line":188},[173,1258,279],{"emptyLinePlaceholder":278},[173,1260,1261],{"class":175,"line":194},[173,1262,1263],{"class":1222},"# Or in the UI: Browse -> DAGs -> [Your DAG] -> \"Next Run\" column\n",[26,1265,1267],{"id":1266},"_2-understand-the-data-interval","2. Understand the Data Interval",[153,1269,1271],{"className":167,"code":1270,"language":169,"meta":161,"style":161},"from airflow import DAG\nfrom datetime import datetime\n\ndag = DAG(\n    'debug_example',\n    start_date=datetime(2024, 1, 1),\n    schedule_interval='0 0 * * *',\n)\n\n# In your task, you can access:\n# {{ data_interval_start }} - Start of the scheduled period\n# {{ data_interval_end }} - End of the scheduled period (when DAG runs)\n",[135,1272,1273,1277,1281,1285,1289,1294,1298,1302,1306,1310,1315,1320],{"__ignoreMap":161},[173,1274,1275],{"class":175,"line":176},[173,1276,268],{},[173,1278,1279],{"class":175,"line":182},[173,1280,393],{},[173,1282,1283],{"class":175,"line":188},[173,1284,279],{"emptyLinePlaceholder":278},[173,1286,1287],{"class":175,"line":194},[173,1288,191],{},[173,1290,1291],{"class":175,"line":200},[173,1292,1293],{},"    'debug_example',\n",[173,1295,1296],{"class":175,"line":206},[173,1297,203],{},[173,1299,1300],{"class":175,"line":212},[173,1301,553],{},[173,1303,1304],{"class":175,"line":300},[173,1305,215],{},[173,1307,1308],{"class":175,"line":306},[173,1309,279],{"emptyLinePlaceholder":278},[173,1311,1312],{"class":175,"line":364},[173,1313,1314],{},"# In your task, you can access:\n",[173,1316,1317],{"class":175,"line":369},[173,1318,1319],{},"# {{ data_interval_start }} - Start of the scheduled period\n",[173,1321,1322],{"class":175,"line":440},[173,1323,1324],{},"# {{ data_interval_end }} - End of the scheduled period (when DAG runs)\n",[26,1326,1328],{"id":1327},"_3-test-scheduling-without-running","3. Test Scheduling Without Running",[153,1330,1332],{"className":1213,"code":1331,"language":1215,"meta":161,"style":161},"# Parse the schedule and show next runs\nairflow dags test \u003Cdag_id> 2024-01-01\n",[135,1333,1334,1339],{"__ignoreMap":161},[173,1335,1336],{"class":175,"line":176},[173,1337,1338],{"class":1222},"# Parse the schedule and show next runs\n",[173,1340,1341,1343,1345,1348,1350,1352,1354,1356],{"class":175,"line":182},[173,1342,1229],{"class":1228},[173,1344,1233],{"class":1232},[173,1346,1347],{"class":1232}," test",[173,1349,1240],{"class":1239},[173,1351,1243],{"class":1232},[173,1353,1247],{"class":1246},[173,1355,1250],{"class":1239},[173,1357,1358],{"class":1232}," 2024-01-01\n",[26,1360,1362],{"id":1361},"_4-common-issue-dag-not-running","4. Common Issue: DAG Not Running",[15,1364,1365],{},"Check these in order:",[1367,1368,1369,1376,1385,1390],"ol",{},[234,1370,1371,1372,1375],{},"Is the DAG paused? (",[135,1373,1374],{},"airflow dags unpause \u003Cdag_id>",")",[234,1377,1378,1379,1381,1382,1384],{},"Is ",[135,1380,77],{}," in the past? (Future ",[135,1383,77],{}," = won't run yet)",[234,1386,1378,1387,1389],{},[135,1388,919],{}," and the scheduler already passed the start_date?",[234,1391,1392,1393,1396,1397],{},"Check the scheduler logs: ",[135,1394,1395],{},"airflow scheduler"," output or ",[135,1398,1399],{},"\u002Fvar\u002Flog\u002Fairflow\u002Fscheduler\u002F",[10,1401,1403],{"id":1402},"best-practices","Best Practices",[1367,1405,1406,1414,1423,1435,1444,1452],{},[234,1407,1408],{},[58,1409,1410,1411,1413],{},"Always set ",[135,1412,919],{}," unless you need backfill",[234,1415,1416],{},[58,1417,1418,1419,1422],{},"Use ",[135,1420,1421],{},"pendulum"," for timezone-aware datetimes",[234,1424,1425,1430,1431,1434],{},[58,1426,1427,1428],{},"Don't use dynamic ",[135,1429,77],{}," (e.g., ",[135,1432,1433],{},"datetime.now()",") - it causes unpredictable behavior",[234,1436,1437],{},[58,1438,1439,1440,1443],{},"Test scheduling with ",[135,1441,1442],{},"airflow dags test"," before deploying",[234,1445,1446,1451],{},[58,1447,1448,1449],{},"Use descriptive ",[135,1450,137],{}," - cron strings are opaque; add a comment",[234,1453,1454,1460],{},[58,1455,1456,1457,1459],{},"Consider using ",[135,1458,141],{}," for complex scheduling"," instead of cramming logic into cron expressions",[10,1462,1464],{"id":1463},"quick-reference-cron-to-airflow-mapping","Quick Reference: Cron to Airflow Mapping",[31,1466,1467,1480],{},[34,1468,1469],{},[37,1470,1471,1474,1477],{},[40,1472,1473],{},"Cron",[40,1475,1476],{},"Airflow schedule_interval",[40,1478,1479],{},"Note",[50,1481,1482,1497,1512,1527,1541],{},[37,1483,1484,1489,1494],{},[55,1485,1486],{},[135,1487,1488],{},"@yearly",[55,1490,1491],{},[135,1492,1493],{},"'0 0 1 1 *'",[55,1495,1496],{},"Once a year",[37,1498,1499,1504,1509],{},[55,1500,1501],{},[135,1502,1503],{},"@monthly",[55,1505,1506],{},[135,1507,1508],{},"'0 0 1 * *'",[55,1510,1511],{},"First day of month",[37,1513,1514,1519,1524],{},[55,1515,1516],{},[135,1517,1518],{},"@weekly",[55,1520,1521],{},[135,1522,1523],{},"'0 0 * * 0'",[55,1525,1526],{},"Sunday midnight",[37,1528,1529,1534,1538],{},[55,1530,1531],{},[135,1532,1533],{},"@daily",[55,1535,1536],{},[135,1537,239],{},[55,1539,1540],{},"Midnight",[37,1542,1543,1548,1553],{},[55,1544,1545],{},[135,1546,1547],{},"@hourly",[55,1549,1550],{},[135,1551,1552],{},"'0 * * * *'",[55,1554,1555],{},"Top of every hour",[10,1557,1559],{"id":1558},"related-tools","Related Tools",[231,1561,1562],{},[234,1563,1564,1569],{},[1565,1566,1568],"a",{"href":1567},"\u002Ftools\u002Fcron-parser","Cron Parser"," - Validate and understand cron expressions",[1571,1572,1573],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":161,"searchDepth":182,"depth":182,"links":1575},[1576,1577,1581,1586,1594,1598,1602,1607,1613,1614,1615],{"id":12,"depth":182,"text":13},{"id":23,"depth":182,"text":24,"children":1578},[1579,1580],{"id":28,"depth":188,"text":29},{"id":144,"depth":188,"text":145},{"id":218,"depth":182,"text":219,"children":1582},[1583,1584,1585],{"id":222,"depth":188,"text":223},{"id":311,"depth":188,"text":312},{"id":374,"depth":188,"text":375},{"id":525,"depth":182,"text":526,"children":1587},[1588,1589,1590,1591,1592,1593],{"id":529,"depth":188,"text":530},{"id":564,"depth":188,"text":565},{"id":599,"depth":188,"text":600},{"id":634,"depth":188,"text":635},{"id":669,"depth":188,"text":670},{"id":704,"depth":188,"text":705},{"id":739,"depth":182,"text":740,"children":1595},[1596,1597],{"id":743,"depth":188,"text":744},{"id":825,"depth":188,"text":826},{"id":953,"depth":182,"text":954,"children":1599},[1600,1601],{"id":957,"depth":188,"text":958},{"id":1043,"depth":188,"text":1044},{"id":1093,"depth":182,"text":1094,"children":1603},[1604,1605,1606],{"id":1097,"depth":188,"text":1098},{"id":1175,"depth":188,"text":1176},{"id":1190,"depth":188,"text":1191},{"id":1205,"depth":182,"text":1206,"children":1608},[1609,1610,1611,1612],{"id":1209,"depth":188,"text":1210},{"id":1266,"depth":188,"text":1267},{"id":1327,"depth":188,"text":1328},{"id":1361,"depth":188,"text":1362},{"id":1402,"depth":182,"text":1403},{"id":1463,"depth":182,"text":1464},{"id":1558,"depth":182,"text":1559},"2026-05-26","Master Airflow cron scheduling. Learn schedule_interval vs timetable, common patterns, traps like start_date misunderstanding, and best practices.","md",{"immutable":278},"\u002Fguides\u002Fairflow-cron-scheduling",{"title":5,"description":1617},"guides\u002Fairflow-cron-scheduling","wV3NtRjtFZbP81GgbOSe5JcEwGexvDRFlbitnHBWCfI",1780401322513]