Batch processing memproses data yang sudah terkumpul secara berkala, misalnya tiap malam. Stream processing (streaming) memproses tiap kejadian begitu datang. Bayangin cuci piring. Cara batch: piring ditumpuk seharian, lalu dicuci sekali malam hari. Hemat air dan sabun, tapi piring bersih baru ada besok. Cara streaming: tiap piring dicuci begitu selesai dipakai. Selalu bersih, tapi kamu bolak-balik ke wastafel seharian. Bedanya bukan mana yang lebih canggih, tapi seberapa cepat hasilnya harus ada, dan berapa harganya.
🧪 Tebakan cepat: pesanan Toko Buku dihitung streaming dengan jendela per minggu, dan satu event pesanan datang telat. Minggu 28 September keluar berapa buku: 13 kayak batch, atau kurang? Tebak dulu, jawabannya ada di bagian "Data telat dan watermark".
Batch, micro-batch, streaming
| Batch | Micro-batch | Streaming | |
|---|---|---|---|
| Kapan diproses | terjadwal, misalnya tiap 00.00 | tiap beberapa detik atau menit, dalam kelompok kecil | tiap event, begitu datang |
| Latency (kejadian sampai hasil) | menit sampai sehari | detik sampai menit | milidetik sampai detik |
| Tool | Airflow + SQL atau Python, dbt | Spark Structured Streaming | Apache Flink, Kafka Streams |
| Contoh | laporan harian, melatih ulang model tiap malam | dashboard yang diperbarui tiap menit | deteksi fraud, stok saat flash sale, alert |
Streaming lebih tepat kalau data harus diproses dalam hitungan detik setelah masuk: menahan pembayaran yang mencurigakan, menjaga stok biar gak terjual melebihi persediaan, dashboard live, peringatan error. Kalau hasil yang terlambat beberapa jam atau sehari masih oke, batch lebih sederhana dan lebih murah.
Latency, kelengkapan, biaya
Tiga hal ini selalu ditukar satu sama lain:
- Latency: berapa lama dari kejadian sampai jawaban. DAG harian Toko Buku (pelajaran Airflow) baru memuat pesanan Senin pukul 00.00 Selasa.
- Kelengkapan: apakah semua data sudah masuk waktu jawaban dihitung. Batch jam 00.00 membaca database setelah harinya habis, jadi semua pesanan sudah ada. Streaming harus memutuskan sendiri kapan satu jendela dianggap selesai.
- Biaya: batch Toko Buku cuma kerja beberapa detik per hari. Streaming butuh broker event (biasanya Kafka) dan prosesor yang nyala 24 jam, plus orang yang menjaganya.
Event time dan processing time
Di streaming, tiap pesanan dikirim sebagai event: pesan kecil berisi order_id, created_at, dan jumlah bukunya. Tiap event punya dua waktu:
- Event time: kapan kejadiannya:
created_at. - Processing time: kapan event itu sampai di prosesor.
Biasanya selisihnya cuma detik. Tapi event pesanan 8 (Maya, Minggu 4 Oktober 20.30) tertahan di queue job yang macet, kayak item 9 yang di-retry. Event itu baru sampai Senin 5 Oktober 12.00, setelah event pesanan 9 (Senin 11.20). Menurut event time, pesanan Maya masuk minggu 28 September. Menurut processing time, masuk minggu 5 Oktober. Pertanyaan pemilik soal kapan orang membeli, jadi yang benar event time.
Jendela: tumbling, sliding, session
Stream gak pernah selesai, jadi "jumlahkan semuanya" harus diganti "jumlahkan per jendela (window) waktu". Ini hasilnya dari 14 pesanan bersih (21 buku), menurut event time:
| Jendela | Artinya | Hasil di Toko Buku |
|---|---|---|
| Tumbling 1 hari | potongan tetap, gak tumpang tindih; tiap event masuk tepat satu jendela | 28 Sep 3, 29 Sep 2, 30 Sep 3, 1 Okt 3, ... , 3 Okt 0, ... , 9 Okt 1 |
| Tumbling 1 minggu | sama, per Senin | minggu 28 Sep 13, minggu 5 Okt 8 |
| Sliding 3 hari, geser 1 hari | jendela tumpang tindih; tiap event masuk 3 jendela | 28 sampai 30 Sep 8, 29 Sep sampai 1 Okt 8, 2 sampai 4 Okt 2 |
| Session, jeda 24 jam | jendela berakhir kalau 24 jam gak ada event; panjangnya beda-beda | 5 session: 3, 5, 4, 6, 3 buku |
Session paling menarik kalau dihitung di batch, karena butuh window function. Di SQLite (Lab dan Playground):
WITH RECURSIVE bersih AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY order_id, book_id ORDER BY id) AS ke
FROM order_items
),
pesanan AS (
SELECT o.id AS order_id, o.created_at, SUM(b.qty) AS buku
FROM orders o
JOIN bersih b ON b.order_id = o.id AND b.ke = 1
GROUP BY o.id, o.created_at
),
jeda AS (
SELECT *, (julianday(created_at) - julianday(LAG(created_at) OVER (ORDER BY created_at))) * 24 AS jam
FROM pesanan
),
sesi AS (
SELECT *, SUM(CASE WHEN jam IS NULL OR jam > 24 THEN 1 ELSE 0 END) OVER (ORDER BY created_at) AS sesi
FROM jeda
)
SELECT MIN(created_at) AS jendela, MAX(created_at) AS terakhir, COUNT(*) AS pesanan, SUM(buku) AS buku
FROM sesi
GROUP BY sesi
ORDER BY sesi;
| jendela | terakhir | pesanan | buku |
|---|---|---|---|
| 2026-09-28 09:15:00 | 2026-09-28 13:02:00 | 2 | 3 |
| 2026-09-29 20:11:00 | 2026-09-30 08:40:00 | 2 | 5 |
| 2026-10-01 10:05:00 | 2026-10-02 12:00:00 | 3 | 4 |
| 2026-10-04 20:30:00 | 2026-10-07 14:45:00 | 5 | 6 |
| 2026-10-08 16:10:00 | 2026-10-09 10:30:00 | 2 | 3 |
pesananmengubah item jadi satu baris per pesanan, tanpa baris dobel: 14 pesanan, 21 buku.jedamenghitung jam sejak pesanan sebelumnya denganLAGdanjulianday(hari, dikali 24 jadi jam). Pesanan 3 datang 31,15 jam setelah pesanan 2, jadi session baru.sesimenjumlah tanda "session baru" dari atas ke bawah: running total yang jadi nomor session.
Data telat dan watermark
Prosesor streaming gak bisa menunggu selamanya sebelum menutup jendela. Dia pakai watermark: jam internal yang bilang "semua event sebelum waktu ini dianggap sudah datang". Bentuk yang umum: event time terbesar yang sudah terlihat, dikurangi waktu tunggu. Jendela ditutup dan hasilnya keluar begitu watermark melewati ujung jendela. Event yang datang setelah jendelanya ditutup namanya telat (late data), dan secara default dibuang.
Ini jendela minggu 28 September (berakhir Senin 5 Okt 00.00), dihitung di Lab dengan cara kerja jendela event time Flink:
| Watermark menunggu | Jendela keluar | Isinya | Pesanan Maya |
|---|---|---|---|
| 0 jam | Senin 5 Okt 11.20, waktu event pesanan 9 datang | 12 buku | dibuang: jendelanya sudah tutup waktu dia datang 12.00 |
| 12 jam | Selasa 6 Okt 09.00, waktu event pesanan 10 datang | 13 buku | dihitung |
Jawabannya 12, dan itu jawaban tebakannya: tanpa waktu tunggu, satu buku hilang tanpa error. Waktu tunggu 12 jam bikin hasilnya lengkap, tapi keluarnya sehari lebih lambat. Watermark cuma maju kalau ada event baru, dan pesanan Toko Buku jarang. Batch harian malah sudah punya angka lengkap 13 sejak Senin 00.00. Event telat juga bisa dikirim ke jalur terpisah (side output) buat dibetulkan belakangan, jadi gak dibuang.
Pertanyaan pemilik gak butuh streaming
Pemilik membaca "buku paling laku per kota per minggu" tiap Senin pagi. Batch harian jam 00.00 (DAG Airflow dari pelajaran sebelumnya) sudah memuat hari Minggu dari database dengan lengkap, termasuk pesanan Maya, cuma dengan kerja beberapa detik per hari. Kalau pakai streaming untuk pertanyaan ini, yang bertambah cuma Kafka, prosesor yang nyala terus, dan urusan watermark, padahal pesanannya cuma 14 dalam dua minggu. Streaming baru layak kalau ada keputusan yang harus diambil dalam hitungan detik: menolak pembayaran palsu, mengunci stok saat flash sale, membunyikan alarm saat checkout gagal beruntun.
Banyak tim pakai keduanya. Arsitektur Lambda menjalankan jalur batch (lengkap) dan jalur streaming (cepat) berdampingan. Risikonya, ada dua kode yang harus menghasilkan angka yang sama. Arsitektur Kappa cuma pakai streaming, dan menghitung ulang dengan memutar ulang event lama dari Kafka. Kafka dibahas di pelajaran Kafka for Data Pipelines, dan dashboard real-time di pelajaran Real-time Analytics Pipeline.
⚠️ Jebakan yang sering ketemu
- Mengelompokkan per processing time. Pesanan Maya pindah ke minggu 5 Oktober: per minggu jadi 12 dan 9, padahal yang benar 13 dan 8.
- Watermark yang terlalu pendek atau terlalu panjang. Kalau terlalu pendek, event telat dibuang diam-diam. Kalau terlalu panjang, hasilnya keluar terlambat.
- Jendela yang gak pernah tutup. Watermark cuma maju kalau ada event. Kalau toko sepi, jendela terakhir menunggu terus.
- Streaming karena terdengar modern. Tanya dulu: siapa yang butuh jawabannya dalam detik? Kalau gak ada, pakai batch.
TL;DR: Batch memproses data yang sudah terkumpul secara terjadwal: sederhana, murah, lengkap, tapi latency-nya menit sampai sehari. Streaming memproses tiap event begitu datang (Flink, Kafka Streams; micro-batch di Spark Structured Streaming): cocok kalau data harus diproses dalam hitungan detik, kayak fraud detection dan dashboard live, tapi biayanya jalan terus karena selalu nyala. Kelompokkan menurut event time (created_at), bukan processing time. Jendela tumbling gak tumpang tindih, sliding tumpang tindih, session berakhir setelah jeda tanpa event (Toko Buku: 5 session dengan jeda 24 jam). Watermark menentukan kapan jendela ditutup: dengan waktu tunggu 0 jam, pesanan Maya yang datang telat dibuang dan minggu 28 September jadi 12 buku; dengan 12 jam jadi 13, tapi sehari lebih lambat. Pertanyaan mingguan pemilik cukup dijawab batch harian. Kafka dibahas di pelajaran Kafka for Data Pipelines.