A backfill creates runs for past dates, for example to load a month that was missed or to reprocess
data after a fix. In Airflow 3 the command airflow backfill create replaces the old
airflow dags backfill, and the scheduler, not your terminal, executes the runs.
Copy and paste
Preview the runs:
airflow backfill create --dag-id sales_daily \
--from-date 2026-05-01 --to-date 2026-05-04 --dry-run
Create them, at most two running at a time:
airflow backfill create --dag-id sales_daily \
--from-date 2026-05-01 --to-date 2026-05-04 \
--max-active-runs 2
Choose what happens to dates that already have a run:
--reprocess-behavior none # default: skip them
--reprocess-behavior failed # rerun the dates whose run failed
--reprocess-behavior completed # rerun every date, failed or successful
Other options:
--run-backwards # most recent date first
--dag-run-conf '{"full_refresh": true}' # passed to every run as dag_run.conf
Which runs are created
The backfill creates one run for every scheduled time between the two dates, both included. A date
without a time means midnight. With a DAG that runs at 06:00, --to-date 2026-05-03 stops at
midnight on 3 May and leaves out the run of 3 May:
$ airflow backfill create --dag-id sales_daily --from-date 2026-05-01 --to-date 2026-05-03 --dry-run
Runs to be attempted:
| 2026-05-01 06:00:00+00:00 |
| 2026-05-02 06:00:00+00:00 |
Write --to-date 2026-05-04, or 2026-05-03T23:59:59, to include it. Backfill runs get run IDs such
as backfill__2026-05-01T06:00:00+00:00, so they are easy to tell apart from scheduled runs.
The DAG must be unpaused
The command only creates the runs. If the DAG is paused, as new DAGs are by default, they stay queued until you unpause it:
airflow dags unpause sales_daily
With catchup=False, unpausing also creates the most recent scheduled run. The scheduler handles
backfill runs after the regular ones in each cycle, so they can wait while other DAGs are busy.
From the UI
On the DAG page, click Trigger and choose Backfill. The form asks for the date range and the
reprocess behaviour: Missing Runs (none), Missing and Errored Runs (failed) or
All Runs (completed). It also offers max active runs, run backwards and an option to unpause the
DAG. A DAG with schedule=None cannot be backfilled.
Make the DAG safe to backfill
- Build every date from
dsorlogical_date, never fromdatetime.now(), or each backfill run loads today; see how to get yesterday’s date. - Make each run idempotent: delete and reload the date, or merge on a key, so that running a date twice does not duplicate rows.
catchup=Falsedoes not prevent backfills. It only stops the scheduler from creating missed runs by itself.
Tested with Airflow 3.3.2 and its scheduler.