Orchestration at scale adalah menjalankan banyak pipeline milik banyak tim yang saling bergantung, tepat urutan, tepat data, dan ketahuan kalau ada yang macet. Satu DAG Airflow dari pelajaran sebelumnya cuma awalnya. Bayangin bandara. Banyak maskapai, banyak pesawat, satu menara kontrol. Pesawat lanjutan ke Makassar menunggu penumpang transit dari Medan yang mendarat telat; dia gak berangkat cuma karena jamnya sudah tiba, lalu meninggalkan separuh penumpangnya. Kalau satu pesawat tertahan terlalu lama, papan bandara menulis DELAYED supaya semua orang tahu. Menara kontrol itu orchestrator, jam keberangkatan itu cron, "berangkat setelah pesawat transit mendarat" itu penjadwalan berbasis data, dan papan DELAYED itu alert.
🧪 Tebakan cepat: Malam Minggu ke Senin, extract MySQL Toko Buku telat sampai 01:30.
penjualandijadwalkan cron 01:00,laris_mingguancron 02:00, dan pemilik membacanya jam 06:00. Laporannya lengkap, kurang, atau gak ada? Tebak dulu, jawabannya ada di bagian "Cron atau data-aware".
Dari satu DAG ke banyak tim
Di pelajaran Airflow, satu DAG mengerjakan semuanya. Begitu tim bertambah, pipeline-nya terpecah, dan yang menyambungkan mereka adalah aset: tabel atau file yang dihasilkan satu pipeline dan dibaca pipeline lain. Graf aset kecil Toko Buku di Lab:
| Aset | Pemilik | Dibaca oleh |
|---|---|---|
raw_order_lines |
tim data, extract MySQL jam 00:05 | penjualan |
penjualan |
tim data, satu partisi per hari | laris_mingguan, segmen_pelanggan |
laris_mingguan |
tim data | pemilik toko, Senin 06:00 |
segmen_pelanggan |
tim marketing | kampanye email |
segmen_pelanggan milik tim lain, di repo lain, dengan jadwal sendiri. Pertanyaannya: kapan dia boleh jalan?
Cron atau data-aware
Ada dua cara memicu penjualan:
- Cron: jalan di jam tetap, misalnya 01:00, siap atau gak siap upstream-nya.
- Data-aware (berbasis aset): jalan begitu upstream-nya diperbarui.
Malam Minggu 4 ke Senin 5 Oktober, replica MySQL tertinggal dan raw_order_lines baru selesai 01:30. Partisi 4 Oktober berisi pesanan 8 milik Maya (1 Laskar Pelangi). Hasil Lab, dijalankan di SQLite:
| Penjadwalan | penjualan[2026-10-04] |
laris_mingguan siap |
Minggu 28 September |
|---|---|---|---|
| cron 01:00 | jalan 01:00, 0 baris | 02:00 | 12 buku, baris "Tidak diketahui" hilang |
| data-aware | jalan 01:31, 1 baris | 01:33 | 13 buku, lengkap |
Dengan cron, laporannya kurang dan datang tepat waktu, tanpa error dan tanpa alarm. Itu jawaban tebakannya. Data-aware sedikit lebih lambat tapi benar, dan tim marketing ikut menunggu data yang lengkap.
Di Airflow 3, penjadwalan berbasis aset ditulis dengan Asset. Kode ini diparse Airflow 3.3.2 tanpa import error:
import pendulum
from airflow.sdk import Asset, dag, task
WIB = "Asia/Jakarta"
raw_order_lines = Asset("raw_order_lines")
penjualan = Asset("penjualan")
@dag(schedule="5 0 * * *", start_date=pendulum.datetime(2026, 9, 28, tz=WIB), catchup=False)
def extract_mysql():
@task(outlets=[raw_order_lines])
def muat_raw() -> None:
... # salin pesanan kemarin dari replica MySQL
muat_raw()
@dag(schedule=[raw_order_lines], start_date=pendulum.datetime(2026, 9, 28, tz=WIB), catchup=False)
def bangun_penjualan():
@task(outlets=[penjualan])
def muat_penjualan() -> None:
... # DELETE lalu INSERT satu tanggal
muat_penjualan()
extract_mysql()
bangun_penjualan()
outlets=[raw_order_lines]: task ini memperbarui aset itu. Begitu task selesai sukses, Airflow mencatat event aset.schedule=[raw_order_lines]: DAG jalan tiap ada event untuk aset itu, bukan di jam tertentu. DAGsegmen_pelanggantim marketing cukup menulisschedule=[penjualan].
Di Dagster (1.13.26), aset adalah pusatnya: tiap fungsi @dg.asset menghasilkan satu tabel, dan automation_condition mengatur kapan dia dibangun ulang. Potongan kode yang dijalankan di laptop dengan DuckDB:
harian = dg.DailyPartitionsDefinition(start_date="2026-09-28", timezone="Asia/Jakarta")
@dg.asset(partitions_def=harian)
def penjualan(context: dg.AssetExecutionContext) -> dg.MaterializeResult:
tanggal = context.partition_key # misalnya "2026-10-04"
... # DELETE lalu INSERT satu tanggal
return dg.MaterializeResult(metadata={"baris": baris})
@dg.asset(
deps=[penjualan],
automation_condition=dg.AutomationCondition.eager(),
freshness_policy=dg.FreshnessPolicy.time_window(fail_window=timedelta(hours=30)),
owners=["team:data"],
)
def laris_mingguan() -> dg.MaterializeResult: ...
AutomationCondition.eager() artinya "bangun ulang begitu upstream berubah". Di Prefect (3.8.8), pipeline-nya fungsi Python biasa dengan @flow dan @task(retries=2, retry_delay_seconds=300); sebuah deployment dijadwalkan dengan cron atau dipicu event lewat automation.
Sensor atau event
Kadang yang ditunggu bukan aset di orchestrator yang sama, misalnya file stok dari marketplace di folder SFTP.
- Sensor mengecek berkala. Mulai 00:00, tiap 5 menit, file datang 03:00: 37 kali cek, 36 sia-sia. Sensor mode poke memegang satu slot worker selama menunggu; sensor deferrable (Airflow) melepas slotnya ke triggerer di antara cek.
- Event: sumbernya mengirim pesan saat siap, dan pipeline bereaksi sekali. Airflow 3 bisa memicu DAG dari pesan antrean lewat
AssetWatcher; Prefect lewat automation; Dagster lewat sensor yang membaca antreannya.
Pakai event kalau sumbernya bisa memberi tahu, sensor kalau gak bisa.
SLA, freshness, dan alert
Pemilik membaca laris_mingguan Senin 06:00. Janji "laporan siap sebelum 06:00" disebut SLA (service level agreement), dan freshness adalah seberapa baru datanya. Ada dua alarm yang dibutuhkan:
- Alarm gagal: task yang tetap gagal setelah retry (3 percobaan, jeda 5 menit) mengirim notifikasi ke chat atau email.
- Alarm kesegaran: jam 06:00, cek apakah
laris_mingguansudah diperbarui malam ini. Kalau extract gagal dan penjadwalannya data-aware, aset hilirnya gak jalan, dan cek ini berbunyi:ALERT laris_mingguan belum diperbarui malam ini (batas 06:00). Pemilik tahu laporannya belum ada, bukan membaca angka salah.
Di Airflow 3, fitur SLA lama dihapus dan diganti Deadline Alerts. Dagster punya FreshnessPolicy seperti di kode atas (gagal kalau lebih dari 30 jam gak diperbarui). dbt punya source freshness dari pelajaran dbt. Hati-hati: cek kesegaran gak tahu isinya benar atau gak. Dengan cron di malam telat tadi, ceknya bilang OK, karena laporannya memang diperbarui jam 02:00. Tes kualitas data (pelajaran kualitas data) yang menangkap isinya.
Backfill besar dan idempotensi
Backfill adalah menjalankan ulang aset untuk tanggal-tanggal lama, misalnya setelah aturan transform diperbaiki. Backfill penjualan 28 September sampai 4 Oktober dengan Dagster 1.13.26, satu partisi sekali jalan, lalu laris_mingguan:
for tanggal in ["2026-09-28", "2026-09-29", "2026-09-30", "2026-10-01", "2026-10-02", "2026-10-03", "2026-10-04"]:
hasil = dg.materialize([penjualan], partition_key=tanggal)
meta = hasil.asset_materializations_for_node("penjualan")[0].metadata
print(tanggal, hasil.success, meta["baris"].value)
hasil = dg.materialize([laris_mingguan]) # metadata-nya: jumlah buku minggu 28 September
print("laris_mingguan", hasil.success, hasil.asset_materializations_for_node("laris_mingguan")[0].metadata["buku_minggu_28_sep"].value)
2026-09-28 True 3
2026-09-29 True 1
2026-09-30 True 2
2026-10-01 True 2
2026-10-02 True 1
2026-10-03 True 0
2026-10-04 True 1
laris_mingguan True 13
Backfill aman cuma kalau tiap partisi idempoten, seperti di pelajaran ETL: DELETE tanggal itu dulu, baru INSERT. Dengan INSERT saja, tiap partisi yang sudah terisi jadi dobel, dan minggu itu jadi 26 buku. Di skala besar, waktunya juga dihitung. Setahun = 365 partisi; tiap partisi 2 menit, paling banyak 4 bersamaan: 92 gelombang, 184 menit. Batas paralel itu disengaja, supaya replica MySQL gak dibanjiri 365 query sekaligus.
Biaya
Orchestrator sendiri nyala 24 jam: scheduler, worker, database metadata, dan untuk Airflow juga triggerer dan API server. Sensor poke yang lama menunggu memakan slot worker. Backfill membayar compute warehouse untuk tiap partisi. Layanan terkelola memindahkan urusan server ke vendor, dengan harga bulanan: Astronomer, Google Cloud Composer, dan Amazon MWAA untuk Airflow; Dagster+ untuk Dagster; Prefect Cloud untuk Prefect. Untuk Toko Buku, cron plus satu DAG dari pelajaran Airflow masih cukup; orchestration at scale mulai terasa perlu waktu ada beberapa tim dan puluhan pipeline yang saling bergantung.
Airflow, Dagster, Prefect
Ketiganya open source (Apache 2.0) dan ditulis dengan Python. Versi per Oktober 2026: Airflow 3.3.2 (17 September 2026), Dagster 1.13.26 (9 Oktober 2026), Prefect 3.8.8 (6 Oktober 2026).
| Airflow | Dagster | Prefect | |
|---|---|---|---|
| Unit utama | DAG dan task | aset (tabel atau file) | flow dan task (fungsi Python) |
| Data-aware | aset sejak 3.0 (dataset sejak 2.4) | inti desainnya, plus partisi dan backfill | trigger dari event lewat automation |
| Coba di laptop | airflow dags test |
dg.materialize(...) |
panggil fungsi flow-nya langsung |
| Kekuatan khas | ekosistem operator dan provider terbesar | lineage aset, integrasi dbt | pipeline Python yang dinamis |
Prefect dan Dagster lahir sesudah Airflow, dengan API Python native, penjadwalan berbasis data, dan pengalaman developer yang dirancang dari awal; itu perbedaan yang paling sering disebut. Airflow menyusul: TaskFlow API sejak 2.0, dataset sejak 2.4, aset dan import airflow.sdk di 3.0. Tim yang sudah punya ratusan DAG Airflow biasanya lebih untung meneruskannya; tim yang berpikir dalam tabel dbt sering cocok dengan Dagster; tim yang punya banyak script Python dan butuh retry serta trigger cepat sering cocok dengan Prefect. Pilih dari kebutuhan tim, bukan dari mana yang terdengar paling baru.
⚠️ Jebakan yang sering ketemu
- Cron untuk dependensi antar tim. "Tim data biasanya selesai jam 01:00" adalah tebakan. Malam yang telat menghasilkan laporan yang tepat waktu tapi salah. Gunakan aset.
- Backfill tanpa idempotensi.
INSERTsaja menggandakan tiap partisi yang dijalankan ulang.DELETElaluINSERTper tanggal, dalam satu transaksi. - Alert untuk semuanya. Alarm yang bunyi tiap hari akhirnya diabaikan. Bunyikan untuk yang perlu tindakan: gagal setelah retry, dan batas kesegaran yang dijanjikan ke pemakai.
- Sensor poke berjam-jam. Tiap sensor yang menunggu memegang slot worker. Pakai deferrable, interval lebih jarang, atau event.
TL;DR: Orchestration at scale menyambung pipeline banyak tim lewat aset: raw_order_lines, penjualan, laris_mingguan, dan segmen_pelanggan milik tim marketing. Cron menjalankan di jam tetap; data-aware menjalankan saat upstream diperbarui. Saat extract telat sampai 01:30, cron membuat laporan tepat waktu tapi kurang (12 buku), data-aware membuatnya 01:33 dan lengkap (13). Airflow 3 menulisnya outlets=[Asset(...)] dan schedule=[Asset(...)], Dagster dengan @dg.asset dan AutomationCondition.eager(), Prefect dengan deployment dan automation. Sensor mengecek berkala (37 cek untuk menunggu 3 jam), event memicu sekali. Pasang alarm gagal dan cek kesegaran (Deadline Alerts di Airflow 3, FreshnessPolicy di Dagster), dan ingat cek kesegaran gak menilai isi. Backfill aman cuma dengan partisi idempoten (INSERT saja: 26 buku, bukan 13), dan dibatasi paralelnya. Airflow 3.3.2, Dagster 1.13.26, dan Prefect 3.8.8 dipilih dari kebutuhan tim, bukan diperingkat.