Backfill dan catchup

Memahami mekanika catchup dan menjalankan backfill untuk memuat ulang riwayat dengan aman.

Daftar isi

Pipeline data jarang sekali diaktifkan tepat pada hari data pertamanya tersedia. Sumber data biasanya sudah mengumpulkan riwayat berhari-hari atau berminggu-minggu sebelum pipeline diaktifkan, dan pipeline juga dapat berhenti sehingga sebagian interval terlewat. Topik ini membahas dua mekanisme Airflow untuk menutup celah tersebut, yaitu catchup, yang mengisi interval terlewat secara otomatis melalui scheduler, dan backfill, yang mengisi rentang tertentu melalui perintah CLI. Setelah membaca topik ini, perilaku kedua mekanisme pada Airflow 3.x dapat diprediksi dan backfill dapat dijalankan dengan aman.

Mekanika catchup#

Catchup adalah perilaku scheduler yang membuat dag run untuk setiap data interval yang terlewat sejak start_date hingga hari ini. Apabila sebuah DAG harian diaktifkan pada 2026-11-04 dengan start_date 2026-11-01 dan catchup aktif, scheduler membuat dag run untuk interval 1, 2, dan 3 November terlebih dahulu sebelum mengejar interval hari ini. Jika catchup tidak aktif, scheduler hanya membuat run untuk interval yang dimulai setelah DAG diaktifkan, sehingga riwayat sebelumnya tetap kosong sampai diisi secara manual.

Airflow 3.x menetapkan catchup tidak aktif secara bawaan. Nilainya dikendalikan oleh konfigurasi scheduler.catchup_by_default, dan perintah berikut menunjukkan nilai bawaan tersebut pada instalasi latihan:

bash
export AIRFLOW__CORE__LOAD_EXAMPLES=False AIRFLOW_HOME=/tmp/ra-backfill-dan-catchup
# nilai bawaan catchup pada scheduler
airflow config get-value scheduler catchup_by_default
text Keluaran
False

Catchup dapat diaktifkan per DAG melalui argumen catchup pada decorator @dag. Pada Airflow 3.x, DAG yang menetapkan catchup=True wajib menyertakan start_date, dan eksekusi definisi DAG berikut akan gagal dengan pesan error apabila start_date tidak disertakan:

python Contoh: DAG dengan catchup aktif
import pendulum
from airflow.sdk import dag, task

@dag(schedule="@daily", start_date=pendulum.datetime(2026, 11, 1, tz="Asia/Jakarta"), catchup=True)
def dag_laporan():
    @task
    def hitung():
        return 1

    hitung()

dag_laporan()

Backfill manual melalui CLI#

Backfill manual mengisi rentang tanggal tertentu tanpa bergantung pada perilaku catchup. Perintah lama airflow dags backfill yang dikenal luas pada Airflow 2.x sudah dihapus pada versi 3.x dan digantikan oleh airflow backfill create. Perintah baru ini membuat pekerjaan backfill beserta rentangnya, kemudian run yang dihasilkan dieksekusi oleh scheduler.

DAG latihan berikut adalah pipeline harian dengan dua task dan jadwal @daily. Karena argumen catchup tidak disetel, run untuk interval sebelum DAG diaktifkan tidak dibuat secara otomatis:

python dag_harian.py
from airflow.providers.standard.operators.bash import BashOperator
from airflow.sdk import dag

@dag(schedule="@daily")
def dag_harian():
    siapkan = BashOperator(task_id="siapkan", bash_command="echo menyiapkan data")
    arsipkan = BashOperator(task_id="arsipkan", bash_command="echo mengarsipkan data")
    siapkan >> arsipkan

dag_harian()

Berkas DAG di atas diparse tanpa keluaran apa pun dan belum memerlukan basis data. Langkah berikut menyiapkan lingkungan latihan yang bersih, memasang basis data metadata, lalu mendaftarkan DAG ke basis data melalui reserialize:

bash
export AIRFLOW__CORE__LOAD_EXAMPLES=False AIRFLOW_HOME=/tmp/ra-backfill-dan-catchup
# lingkungan latihan bersih agar langkah dapat diulang dari awal
rm -rf $AIRFLOW_HOME
mkdir -p $AIRFLOW_HOME/dags
cp dag_harian.py $AIRFLOW_HOME/dags/
bash
export AIRFLOW__CORE__LOAD_EXAMPLES=False AIRFLOW_HOME=/tmp/ra-backfill-dan-catchup
# pasang basis data metadata pada instalasi latihan
airflow db migrate > $AIRFLOW_HOME/migrate.log 2>&1
bash
export AIRFLOW__CORE__LOAD_EXAMPLES=False AIRFLOW_HOME=/tmp/ra-backfill-dan-catchup
# daftarkan DAG ke basis data
airflow dags reserialize > $AIRFLOW_HOME/reserialize.log 2>&1

Setelah DAG terdaftar, backfill untuk rentang 1 sampai 3 November 2026 dibuat dengan perintah airflow backfill create. Opsi --from-date dan --to-date menentukan rentang logis yang diisi:

bash
export AIRFLOW__CORE__LOAD_EXAMPLES=False AIRFLOW_HOME=/tmp/ra-backfill-dan-catchup
# buat backfill untuk rentang tiga hari
airflow backfill create --dag-id dag_harian --from-date 2026-11-01 --to-date 2026-11-03 > $AIRFLOW_HOME/backfill.log 2>&1

Perintah tersebut berakhir dengan status sukses dan membuat tiga dag run sekaligus. Daftar run dapat diperiksa dengan airflow dags list-runs:

bash
export AIRFLOW__CORE__LOAD_EXAMPLES=False AIRFLOW_HOME=/tmp/ra-backfill-dan-catchup
# daftar dag run hasil backfill
airflow dags list-runs dag_harian
text Keluaran
dag_id     | run_id                              | state  | run_after                 | logical_date              | start_date | end_date
===========+=====================================+========+===========================+===========================+============+=========
dag_harian | backfill__2026-11-03T00:00:00+00:00 | queued | 2026-11-03T00:00:00+00:00 | 2026-11-03T00:00:00+00:00 |            |
dag_harian | backfill__2026-11-02T00:00:00+00:00 | queued | 2026-11-02T00:00:00+00:00 | 2026-11-02T00:00:00+00:00 |            |
dag_harian | backfill__2026-11-01T00:00:00+00:00 | queued | 2026-11-01T00:00:00+00:00 | 2026-11-01T00:00:00+00:00 |            |

Tiga run terbentuk dengan awalan backfill__ pada run_id, satu untuk setiap logical_date pada rentang yang diminta. Statusnya queued karena eksekusi run backfill adalah tugas scheduler. Pada instalasi latihan yang tidak menjalankan layanan jangka panjang, status run tetap queued, sedangkan pada instalasi produksi dengan scheduler aktif run tersebut dieksekusi berurutan hingga berstatus success.

Backfill yang aman#

Backfill yang aman memerlukan task yang idempoten, yaitu task yang efek akhirnya sama meskipun dijalankan berkali-kali. Backfill menjalankan ulang task untuk interval lama, sehingga task yang menambah data tanpa pemeriksaan akan menduplikasi hasil interval tersebut. Pola nama berkas terpartisi dan penimpaan hasil per interval yang dibahas pada topik task idempoten membuat run ulang backfill tidak meninggalkan data ganda.

Perilaku terhadap run yang sudah ada dikendalikan oleh opsi --reprocess-behavior dengan tiga nilai. Nilai none (bawaan) tidak membuat run baru untuk logical_date yang sudah punya run. Nilai completed membuat run ulang untuk run yang sudah selesai, dan nilai failed hanya untuk run yang gagal. Opsi --run-backwards mengubah urutan eksekusi agar tanggal terbaru diproses lebih dulu, dan hal ini berguna apabila hasil terbaru dibutuhkan lebih segera. Opsi ini tidak mendukung task yang memiliki dependensi antar hari.

Kesalahan umum#

Menganggap backfill terjadi otomatis. Banyak materi Airflow 2.x menyebut catchup aktif secara bawaan, sedangkan Airflow 3.x menetapkannya tidak aktif. Pipeline yang dipindahkan tanpa catchup=True atau tanpa backfill manual akan memiliki riwayat kosong yang tampak seperti kegagalan pipeline, padahal run-nya memang tidak pernah dibuat.

Menjalankan ulang pekerjaan backfill yang masih berjalan. Error AlreadyRunningBackfill muncul karena Airflow melarang dua pekerjaan backfill untuk DAG yang sama berjalan bersamaan. Periksa status pekerjaan lama terlebih dahulu, atau gunakan --reprocess-behavior pada pekerjaan berikutnya alih-alih membuat pekerjaan yang tumpang tindih.

Ringkasan#

  • Catchup mengisi dag run untuk interval terlewat secara otomatis, dan pada Airflow 3.x tidak aktif secara bawaan (scheduler.catchup_by_default=False).
  • Pada tingkat DAG, catchup diaktifkan dengan catchup=True yang wajib disertai start_date.
  • Perintah airflow dags backfill dihapus pada 3.x dan digantikan oleh airflow backfill create --dag-id --from-date --to-date, dan run yang dihasilkannya dieksekusi oleh scheduler.
  • Backfill yang aman mensyaratkan task idempoten dan perilaku run ulang yang dikendalikan oleh --reprocess-behavior.

Referensi#