# Scheduling: Cron, Intervals and Catchup — Apache Airflow: Orchestrate Data Pipelines

Source: https://www.geekswithgeeks.com/en/airflow/dag-scheduling

> Choose a schedule, understand data intervals and decide whether to catch up on past runs.

## The run is for the interval that just ended

Set `schedule` to a preset (`"@daily"`, `"@hourly"`), a **cron** string (`"0 6 * * *"` for 06:00 daily), or a `timedelta`. Airflow thinks in **data intervals**: a daily run whose logical date is 1 October covers 1 Oct 00:00 to 2 Oct 00:00 and actually starts **after** that interval has ended, at midnight on 2 October. `start_date` is when scheduling may begin. **`catchup`** controls whether Airflow creates runs for every missed interval since `start_date` (True) or only the latest (False). Be careful with `catchup=True` and a distant `start_date`: it can create hundreds of runs at once.

## Interval and catchup arithmetic, run

I ran this plain-Python calculation. A run with logical date 1 Oct covers 1 to 2 Oct and executes at 2 Oct 00:00. With `start_date` 1 Sep and `catchup=True` on 1 Oct, 30 daily runs (1 to 30 Sep) would be created.

```python
from datetime import datetime, timedelta, date

logical = datetime(2026, 10, 1)
end = logical + timedelta(days=1)
print("interval", logical.date(), "->", end.date(), "runs at/after", end.isoformat())

start, now = date(2026, 9, 1), date(2026, 10, 1)
runs = [start + timedelta(days=i) for i in range((now - start).days)]
print(len(runs), runs[0], runs[-1])
```

Output:

```
interval 2026-10-01 -> 2026-10-02 runs at/after 2026-10-02T00:00:00
30 2026-09-01 2026-09-30
```

## Use UTC and be explicit

Airflow works in UTC internally. If your business thinks in India Standard Time (UTC+5:30), define the timezone deliberately with a timezone-aware `start_date`, and remember that 06:00 IST is 00:30 UTC.

**Quiz:** What does `catchup=False` do?

- [ ] Deletes old runs
- [ ] Disables the DAG
- [x] Creates only the latest run instead of one per missed interval
- [ ] Makes the DAG run twice

*Answer:* Creates only the latest run instead of one per missed interval. Without catchup, Airflow does not backfill every interval since start_date.
