Schedule icon
Request icon
OutputValues icon
Log icon
If icon
Pause icon
Fail icon
Loop icon
TriggerDagRun icon
SlackIncomingWebhook icon

Airflow Paused DAG Missed Run Backfill Guard

Detect missing Airflow DAG runs and backfill bounded logical dates safely with approval and verification.

Categories
DataInfrastructure

Safety

A paused DAG can skip scheduled intervals without producing a failed run. The downstream table is short while Airflow reports no error. This flow only triggers dates that have no run in the audited window, caps the request and verifies the resulting run list.

Guard What it stops
Inclusive window and daily logical-date subtraction Backfilling dates outside the audited DAG window
max_backfill_count An unbounded catch-up after a long maintenance pause
auto_remediate plus dry_run Accidental writes from the scheduled safe path
Pause with explicit approval Starting runs without a human review of the exact dates
Fresh run-list read after approval Applying a stale plan after another actor created a run
Loop concurrencyLimit: 1 Flooding the Airflow pool or changing chronological order
Post-run run-list and state verification Treating an accepted trigger as proof that the partition recovered

How it works

  1. read_runs_before (io.kestra.plugin.core.http.Request) reads Airflow's DAG run list and plan_missing (io.kestra.plugin.core.output.OutputValues) subtracts present logical dates from the inclusive daily UTC window.
  2. log_plan records the exact missing count and the bounded request. The scheduled trigger is disabled and forces auto_remediate: false and dry_run: true.
  3. Only auto_remediate: true, dry_run: false and a non-empty plan reach approve_backfill (io.kestra.plugin.core.flow.Pause). A declined pause leaves Airflow unchanged.
  4. read_runs_after_pause and plan_after_pause repeat the detector. stale_plan_check fails before any write when the approved list changed.
  5. backfill_missing_dates (io.kestra.plugin.core.flow.Loop, concurrencyLimit: 1) calls io.kestra.plugin.airflow.dags.TriggerDagRun with each logical date and waits for its terminal state before moving to the next date.
  6. read_runs_after_backfill reads Airflow again and verify_backfill fails when a requested date is missing or failed. The errors block sends a Slack alert for execution failures.

What you get

  • A measurable list of absent daily DAG runs instead of an alert that only sees failed runs.
  • A bounded chronological backfill with a human approval point and stale-plan protection.
  • Airflow-native verification of every requested logical date after the write.
  • A disabled safe-mode schedule and an auditable Kestra execution for every audit.

Who it's for

  • Data platform teams whose Airflow DAGs feed partitioned tables.
  • On-call engineers investigating a maintenance pause or scheduler outage.
  • Operators who need a controlled catch-up path that cannot flood an Airflow pool.

Why orchestrate this with Kestra

Airflow records no failed run for an interval that never created a run, so its scheduler and task alerts cannot identify the missing partition by themselves. Kestra adds the bounded date arithmetic, approval pause, sequential trigger loop, stale-plan check and independent read-back in one auditable execution.

Tested end to end

Tested against Kestra 2.0.5 and Apache Airflow 2.9.3 with a pinned Airflow test fixture. The fixture uses a daily DAG with intentionally absent logical dates. The evidence packet records healthy, dry-run, declined approval, remediation, repeat, ineffective and stale-plan cases with Airflow CLI counts before and after.

Case Execution Result
Healthy control 3rzXh61AWXDTNZB2xMG2yQ SUCCESS, 0 missing dates, no triggers
Degraded dry run 7etsV9rfuyqbjdqGCQ4W3u SUCCESS, 3 missing dates listed, no triggers
Declined approval rVggGIMXdCmdy0K5upL3j SUCCESS, approval false, no triggers
Remediation 543QsR1QtZllZ44ubXitSX SUCCESS, 3 requested dates, verification bad=0
Repeat 6tHSiQN9n5Icg8Ej8xKUDC SUCCESS, 0 missing dates, no duplicate triggers
Ineffective write 7lMUcw4of6d6dwaaODIBuy FAILED, Airflow run ended failed and verification reported the date
Approval race 5mEMTgs22yhe7W3CzJRyou FAILED before write, stale plan named the externally created date

Prerequisites

  • Airflow 2.x with the stable REST API enabled and a DAG scheduled daily in UTC.
  • A Kestra worker that can reach the Airflow webserver on the same network.
  • Airflow permission to list DAG runs and create DAG runs for the target DAG.

Secrets

  • POSTGRES_USERNAME and POSTGRES_PASSWORD: Airflow REST API basic-auth credentials for this flow. Use your deployment's secret backend to store the Airflow user and password under these keys.
  • SLACK_WEBHOOK_URL: Slack incoming webhook used by the errors block.

Inputs

Input Type Default Purpose
airflow_base_url STRING http://localhost:8080 Airflow URL from the Kestra worker
dag_id STRING target_dag DAG to audit and backfill
window_start STRING 2026-10-01T00:00:00Z Inclusive UTC start
window_end STRING 2026-10-05T00:00:00Z Inclusive UTC end
max_backfill_count INT 3 Maximum requested dates
auto_remediate BOOL false Enables approval and writes
dry_run BOOL true Keeps execution read-only

Quick start

  1. Start a pinned Airflow test fixture using the reproduction steps and create the POSTGRES_USERNAME, POSTGRES_PASSWORD and SLACK_WEBHOOK_URL secrets.
  2. Import this flow into namespace company.team and run it with the default window. Confirm the plan reports the fixture's absent dates and starts no runs.
  3. Run with auto_remediate: true and dry_run: false, resume the Pause with approved: true and confirm airflow dags list-runs shows one successful run for each requested logical date.
  4. Run the same inputs again. The detector should report zero missing dates and trigger no new runs.

How to extend

  • Change the schedule interval only when the expected logical-date generator and the DAG's timetable use the same UTC cadence.
  • Add a second independent partition check when a DAG run can succeed without writing its downstream table.
  • Route the errors message to paging when a failed backfill needs immediate operator action.

Limits: this blueprint assumes one daily UTC interval and an Airflow API response containing all runs in the requested limit. It proves run existence and terminal state, not downstream table contents. Increase limit and add pagination before using it for a DAG with more than 1000 runs in the response.

Links

This blueprint was created by zkasuran.

See How

New to Kestra?

Use blueprints to kickstart your first workflows.