NATS JetStream vs Kafka untuk Tim yang Tidak Butuh Skala Kafka

Foto oleh D Gore via Wikimedia Commons (CC BY-SA 2.0)
Untuk mayoritas backend, ya. JetStream menyediakan stream tahan-lama yang bisa diputar ulang, consumer push dan pull, serta pengiriman at-least-once atau exactly-once. Ia bukan pengganti ketika Anda secara spesifik membutuhkan ekosistem konektor Kafka Connect, throughput jutaan pesan per detik yang berkelanjutan, atau retensi jangka panjang berskala petabyte.
Publisher melampirkan ID pesan unik yang digunakan server untuk deduplikasi pesan dalam jendela yang dapat dikonfigurasi, mencegah publish ganda. Di sisi consumer, double-acknowledgment mengonfirmasi bahwa pesan telah diterima dan diproses. Bersama-sama keduanya memberikan semantik exactly-once tanpa koordinasi transaksi yang dibutuhkan Kafka.
Consumer push membuat server mengirim pesan secara otomatis ke sebuah subject, yang sederhana tetapi menawarkan kontrol aliran lebih sedikit. Consumer pull membiarkan klien meminta batch saat siap, memberikan backpressure alami dan penskalaan horizontal. Consumer pull adalah default yang direkomendasikan untuk sebagian besar beban pemrosesan tahan-lama.
Tidak. Kafka 4.0, yang dirilis Maret 2025, menghapus ZooKeeper sepenuhnya dan menggantinya dengan KRaft, lapisan metadata berbasis Raft milik Kafka sendiri. Ini menyederhanakan arsitektur menjadi satu sistem dan menskala hingga jutaan partisi, tetapi tidak menghilangkan perencanaan partisi atau penyetelan consumer group.
JetStream tertanam di dalam satu binary Go nats-server dan diaktifkan dengan satu blok konfigurasi atau flag. Tidak ada JVM untuk disetel, tidak ada ZooKeeper atau controller KRaft terpisah, dan monitoring adalah endpoint HTTP bawaan. Deployment tiga-node ber-cluster berjalan nyaman di sumber daya VPS yang sederhana.

Foto oleh D Gore via Wikimedia Commons (CC BY-SA 2.0)
Ringkasan Utama
Untuk tim yang memproses ribuan pesan per detik alih-alih jutaan, NATS JetStream memberikan stream tahan-lama, consumer push dan pull, serta pengiriman at-least-once atau exactly-once dari satu binary mandiri. Kafka unggul di throughput masif dan retensi panjang, tetapi perencanaan partisi dan beban operasionalnya berlebihan untuk sebagian besar backend.
Setiap beberapa bulan sebuah tim memilih Kafka karena itu adalah jawaban default untuk "kami butuh message log." Lalu mereka menghabiskan satu sprint untuk jumlah partisi, rebalancing consumer group, penyetelan retensi, dan menyambungkan stack observability sebelum satu pun event bisnis mengalir. Saya sudah menyaksikan ini terjadi pada layanan yang puncaknya hanya beberapa ribu pesan per detik. Itu bukan wilayah asli Kafka, dan membayar pajak operasional Kafka untuk berada di sana adalah pertukaran yang buruk.
NATS JetStream adalah lapisan persistensi yang tertanam di dalam server NATS. Jika Anda sudah memahami model subject NATS, Anda mendapatkan stream tahan-lama, riwayat yang bisa diputar ulang, dan jaminan pengiriman hanya dengan membalik satu flag konfigurasi. Tulisan ini membahas stream, consumer, dan realitas operasional menjalankan keduanya, lengkap dengan tabel perbandingan agar Anda bisa memutuskan untuk beban kerja Anda sendiri.
NATS inti bersifat fire-and-forget pub/sub: jika tidak ada subscriber yang mendengarkan, pesan itu hilang. JetStream menambahkan lapisan penyimpanan di atas server yang sama, sehingga pesan yang dipublikasikan ke sebuah subject ditangkap ke dalam sebuah stream dan bisa diputar ulang sesuai permintaan. Tidak ada proses terpisah, tidak ada cluster terpisah, dan tidak ada library klien terpisah. Anda mengaktifkannya dengan satu flag dan tetap memakai model koneksi serta subject yang sudah Anda gunakan.
# Enable JetStream in the server config file
# nats-server.conf
jetstream {
store_dir: "/data/jetstream"
max_memory_store: 1G
max_file_store: 10G
}
# Or just a flag for local dev
nats-server -jsSebuah stream mendefinisikan subject apa yang ditangkapnya dan bagaimana ia menyimpan data. Tiga kebijakan retensi ini penting karena langsung memetakan ke pola backend yang umum.
Consumer adalah tampilan berkeadaan (stateful) ke dalam sebuah stream yang melacak pesan mana yang sudah dilihat sebuah klien. Pull consumer adalah default modern: klien meminta satu batch saat siap, yang memberi Anda backpressure alami dan penskalaan horizontal tanpa perlu mendefinisikan partisi. Beberapa worker bisa berbagi satu pull consumer layaknya queue group, dan server menyeimbangkan beban di antara mereka.
Kebijakan konfirmasi adalah tempat Anda menyetel jaminan pengiriman. Explicit ack berarti setiap pesan harus dikonfirmasi atau akan dikirim ulang setelah timeout — inilah jaminan at-least-once Anda. JetStream juga menawarkan exactly-once menggunakan ID pesan publisher untuk deduplikasi ditambah double-ack saat konsumsi. Bandingkan dengan Kafka, di mana exactly-once membutuhkan transaksi dan idempotent producer yang dikonfigurasi dengan benar di seluruh pipeline.
// TypeScript, using the nats.js client with JetStream
import { connect, AckPolicy } from "nats";
const nc = await connect({ servers: "localhost:4222" });
const jsm = await nc.jetstreamManager();
// Create a durable, file-backed stream
await jsm.streams.add({
name: "ORDERS",
subjects: ["orders.>"],
retention: "limits",
storage: "file",
num_replicas: 3,
});
// Create a durable pull consumer with explicit ack
await jsm.consumers.add("ORDERS", {
durable_name: "order-workers",
ack_policy: AckPolicy.Explicit,
max_deliver: 5,
ack_wait: 30_000_000_000, // 30s in nanoseconds
});
const js = nc.jetstream();
const consumer = await js.consumers.get("ORDERS", "order-workers");
const messages = await consumer.consume({ max_messages: 100 });
for await (const m of messages) {
await handleOrder(m.data);
m.ack();
}Setel max_deliver ke angka terbatas dan pasangkan stream dengan strategi dead-letter. Tanpa batas pengiriman, pesan yang selalu membuat handler Anda melempar error akan dikirim ulang selamanya, diam-diam membakar satu worker dalam loop. Ini adalah padanan JetStream dari poison-pill Kafka dan sering menggigit tim yang mengira pengiriman ulang itu gratis.
Kafka 4.0, yang dirilis Maret 2025, menghapus ZooKeeper sepenuhnya dan menggantinya dengan KRaft, lapisan metadata berbasis Raft milik Kafka sendiri. Itu penyederhanaan yang nyata — satu sistem alih-alih dua, dan cluster yang menskala hingga jutaan partisi. Tetapi KRaft tidak menghilangkan bagian yang benar-benar menyita waktu Anda: perencanaan partisi, rebalancing consumer group, penyetelan retensi dan segment, serta memahami semantik log terdistribusi sebelum Anda bisa men-debug lonjakan lag.
JetStream hadir sebagai satu binary Go tanpa JVM untuk disetel dan tanpa heap untuk diukur. Di VPS yang saya jalankan, deployment NATS tiga-node ber-cluster dengan JetStream aktif muat dengan nyaman dalam memori yang bahkan dianggap penghinaan oleh satu broker Kafka. Replikasi berbasis Raft per stream, monitoring adalah endpoint HTTP bawaan, dan CLI nats yang sama untuk publish juga memeriksa stream dan consumer. Semuanya adalah satu model mental.
Jangan membaca "ringan" sebagai "tak terbatas." JetStream tidak dibangun untuk retensi berskala petabyte atau ekosistem konektor pihak ketiga yang luas seperti yang diberikan Kafka Connect. Jika Anda perlu menyebar ke puluhan data warehouse dan lake, atau Anda benar-benar mendorong jutaan pesan per detik dengan retensi sebulan penuh, Kafka pantas dengan kcompleksitasnya. Sesuaikan alat dengan beban sebenarnya, bukan beban yang Anda bayangkan.
| Dimensi | NATS JetStream | Apache Kafka 4.0 |
|---|---|---|
| Deployment | Satu binary Go, satu flag untuk mengaktifkan, tanpa JVM | Broker berbasis JVM, controller KRaft, penyesuaian memori |
| Unit penskalaan | Consumer di atas subject, tanpa perencanaan partisi | Partisi per topic, direncanakan di awal |
| Jaminan pengiriman | At-least-once secara default, exactly-once via ID pesan plus double-ack | At-least-once, exactly-once via transaksi dan idempotent producer |
| Model retensi | Limits, Work Queue, Interest — per stream | Retensi log berbasis waktu atau ukuran, plus compaction |
| Throughput puncak | Nyaman di ribuan hingga jutaan rendah pesan/detik | Dirancang khusus untuk jutaan pesan/detik berkelanjutan |
| Ekosistem | Ramping, berbasis subject, ramah edge dan multi-tenant | Luas — Kafka Connect, Streams, Schema Registry |
Aturan saya sederhana: pilih Kafka ketika Anda bisa menyebutkan fitur Kafka spesifik yang Anda butuhkan — Connect, throughput masif berkelanjutan, atau riwayat ter-compact yang panjang. Jika jawaban jujur Anda adalah "saya butuh message log tahan-lama yang bisa diputar ulang dengan jaminan pengiriman yang baik," JetStream memberikan itu dengan sebagian kecil dari beban operasional, dan Anda selalu bisa naik kelas nanti jika bebannya benar-benar datang.