Pernah nggak sih kamu lagi desain arsitektur sistem, terus sampai di satu titik: “Gue butuh message queue, tapi pake yang mana ya?”

Kalau kamu pernah (atau sedang) ada di posisi itu, tenang — kamu nggak sendirian. Pertanyaan “RabbitMQ vs Kafka” ini kayak pertanyaan abadi di dunia backend development. Hampir setiap kali ada project baru yang melibatkan microservices atau distributed systems, topik ini pasti muncul.

Gue sendiri udah pernah pakai keduanya di production. Ada yang cocok banget, ada juga yang akhirnya harus ganti di tengah jalan karena ternyata pilihannya kurang pas. Makanya, lewat artikel ini gue mau sharing pengalaman dan insight yang gue dapet, supaya kamu nggak perlu melakukan kesalahan yang sama.

Nggak akan ada jawaban yang “paling benar” di sini. Yang ada adalah: mana yang paling cocok untuk konteks project kamu. So, let’s dive in.


Apa Itu Message Queue dan Kenapa Kamu Butuh?

Sebelum kita adu RabbitMQ vs Kafka, penting banget buat kita sepemahaman dulu soal apa itu message queue dan kenapa hal ini penting.

Bayangkan kamu punya dua layanan dalam sistem kamu: Service A dan Service B. Service A menghasilkan data (producer), dan Service B perlu memproses data itu (consumer). Tanpa message queue, Service A harus langsung panggil Service B secara synchronous. Kalau Service B lagi down atau lambat? Service A ikut-ikutan ngadat.

Di sinilah message queue berperan. Dia jadi perantara — semacam posko tengah — yang menyimpan pesan dari producer sampai consumer siap mengambilnya. Hasilnya?

  • Decoupling: Producer dan consumer nggak perlu tahu-menahu soal satu sama lain.
  • Resilience: Kalau consumer down, pesan nggak hilang. Dia nunggu di queue.
  • Scalability: Kamu bisa nambah consumer tanpa ubah kode producer.
  • Load leveling: Traffic spike? Queue nahan dulu, consumer proses sesuai kemampuannya.

Intinya, message queue bikin sistem kamu lebih robust, scalable, dan toleran terhadap kegagalan. Kalau kamu bikin sistem yang serius — bukan sekadar CRUD sederhana — kemungkinan besar kamu butuh ini.

Tapi masalahnya: ada banyak message queue di luar sana. Dan dua yang paling populer (dan paling sering bikin bingung) adalah RabbitMQ dan Apache Kafka. Meskipun keduanya sering disebut “message queue”, sebenarnya filosofi dan arsitektur di belakangnya sangat berbeda.

So, mari kita bedah satu per satu.


RabbitMQ: Si Reliable Messenger yang Fleksibel

RabbitMQ itu sebenarnya bukan “anak baru” di dunia messaging. Dia udah ada sejak 2007, dibangun di atas protokol AMQP (Advanced Message Queuing Protocol). Dan dia udah terbukti di banyak perusahaan besar selama bertahun-tahun.

Filosofi RabbitMQ

RabbitMQ itu pada dasarnya adalah traditional message broker. Konsepnya sederhana: ada producer yang mengirim pesan ke sebuah exchange, lalu exchange meneruskan pesan itu ke satu atau beberapa queue berdasarkan aturan routing yang sudah ditentukan (yang disebut binding). Consumer kemudian mengambil pesan dari queue tersebut.

Setelah pesan di-acknowledge oleh consumer, pesan itu hilang dari queue. Ini yang membedakan RabbitMQ dari Kafka secara fundamental.

Kelebihan RabbitMQ

  1. Routing yang fleksibel: RabbitMQ punya sistem exchange yang powerful — direct, topic, fanout, headers. Kamu bisa bikin routing logic yang sangat kompleks dan granular. Misalnya, kirim pesan ke queue tertentu berdasarkan pattern di routing key.

  2. Protokol standar: Karena pakai AMQP, ada banyak client library di hampir semua bahasa pemrograman. Nggak perlu install library aneh-aneh.

  3. Message acknowledgment: Pesan nggak hilang sampai consumer benar-benar bilang “oke, gue udah proses.” Kalau consumer crash di tengah jalan, pesan bakal di-redeliver ke consumer lain.

  4. Dead Letter Exchange (DLX): Pesan yang gagal diproses bisa dikirim ke queue khusus untuk di-review nanti. Ini sangat berguna untuk debugging dan error handling.

  5. Plugin ecosystem: Management UI bawaan RabbitMQ itu enak banget buat monitoring. Kamu bisa lihat queue depth, message rate, consumer count, semuanya dari browser.

Kekurangan RabbitMQ

  1. Throughput terbatas: Dibanding Kafka, throughput RabbitMQ lebih rendah. Untuk ratusan ribu pesan per detik, RabbitMQ mulai struggle (meskipun dengan tuning yang tepat, dia masih bisa menangani workload yang cukup besar).

  2. Replay capability terbatas: Setelah pesan di-consume dan di-acknowledge, dia hilang. Kalau kamu mau replay, kamu butuh plugin tambahan atau desain yang lebih rumit.

  3. Clustering yang tricky: RabbitMQ clustering bisa bikin pusing, terutama kalau kamu butuh HA (High Availability) dengan partition tolerance.

Contoh Kode: Mengirim dan Menerima Pesan dengan RabbitMQ (Node.js)

// producer.js — Mengirim pesan ke RabbitMQ
const amqplib = require('amqplib');

async function sendOrder() {
  const connection = await amqplib.connect('amqp://localhost');
  const channel = await connection.createChannel();

  const queue = 'order_queue';
  const message = {
    orderId: 'ORD-2026-001',
    product: 'Laptop ASUS ROG',
    quantity: 1,
    timestamp: new Date().toISOString(),
  };

  await channel.assertQueue(queue, { durable: true });
  channel.sendToQueue(queue, Buffer.from(JSON.stringify(message)), {
    persistent: true,
  });

  console.log(`[Producer] Pesan terkirim: ${message.orderId}`);
  await channel.close();
  await connection.close();
}

sendOrder();
// consumer.js — Menerima pesan dari RabbitMQ
const amqplib = require('amqplib');

async function consumeOrder() {
  const connection = await amqplib.connect('amqp://localhost');
  const channel = await connection.createChannel();

  const queue = 'order_queue';
  await channel.assertQueue(queue, { durable: true });
  channel.prefetch(1); // proses 1 pesan sekaligus

  console.log('[Consumer] Menunggu pesan...');

  channel.consume(queue, (msg) => {
    const order = JSON.parse(msg.content.toString());
    console.log(`[Consumer] Order diterima: ${order.orderId} - ${order.product}`);

    // Simulasi proses
    setTimeout(() => {
      channel.ack(msg); // acknowledge setelah selesai
      console.log(`[Consumer] Order ${order.orderId} selesai diproses.`);
    }, 1000);
  });
}

consumeOrder();

Perhatikan di kode di atas: ada durable: true dan persistent: true. Ini memastikan pesan dan queue survive kalau RabbitMQ restart. Hal-hal kecil kayak gini yang sering kelewat dan bikin pesan hilang di production.


Apache Kafka: Si Event Streaming Powerhouse

Kalau RabbitMQ itu “traditional message broker”, maka Kafka itu filosofinya sangat berbeda. Kafka lahir di LinkedIn pada tahun 2011, dan dirancang dari awal untuk menangani high-throughput event streaming.

Filosofi Kafka

Kafka bukan sekadar message queue — dia adalah distributed commit log. Artinya, pesan yang masuk ke Kafka tidak dihapus setelah dikonsumsi. Pesan tetap ada di topic (yang terdiri dari beberapa partition) sampai TTL-nya habis. Consumer cuma menyimpan offset (posisi terakhir yang dibaca), dan bisa membaca ulang dari offset berapa pun kapan saja.

Ini mengubah segalanya. Kamu nggak cuma mengirim pesan dari A ke B — kamu membangun event log yang bisa dianalisis, di-replay, dan di-stream ke banyak consumer sekaligus.

Kelebihan Kafka

  1. Throughput gila-gilaan: Kafka bisa menangani jutaan pesan per detik. Ini karena desain partisi-nya yang memungkinkan paralelisme tinggi.

  2. Replay & reprocessing: Karena pesan tetap tersimpan, consumer bisa “rewind” dan membaca ulang semua event dari awal. Ini sangat powerful untuk debugging, audit, atau rebuild state.

  3. Consumer groups: Banyak consumer bisa membaca dari topic yang sama secara paralel tanpa pesan duplikat (selama mereka di consumer group yang sama).

  4. Durabilitas tinggi: Data Kafka di-replicate ke beberapa broker. Bahkan kalau satu broker mati, data tetap aman.

  5. Kafka Streams & ksqlDB: Ekosistem Kafka sudah sangat mature. Kamu bisa bikin stream processing application tanpa perlu framework tambahan.

  6. Ordering terjamin per partition: Selama pesan dikirim ke partition yang sama, urutannya terjamin. Ini penting untuk banyak use case.

Kekurangan Kafka

  1. Kompleksitas operasional: Kafka itu berat. Dia butuh ZooKeeper (atau KRaft di versi terbaru), banyak konfigurasi, dan resource yang signifikan. Untuk project kecil, ini bisa overkill.

  2. Latensi lebih tinggi: Karena arsitekturnya yang dioptimalkan untuk throughput, latensi Kafka biasanya lebih tinggi dibanding RabbitMQ (millisecond vs sub-millisecond di beberapa kasus).

  3. Bukan traditional message queue: Kalau kamu butuh fitur queue klasik seperti routing, DLX, atau priority queue, Kafka nggak punya itu out-of-the-box.

  4. Consumer management lebih kompleks: Offset management, rebalancing, consumer group coordination — ini semua butuh pemahaman yang cukup dalam.

  5. Ukuran cluster yang besar: Untuk production, kamu biasanya butuh minimal 3 broker. Ini berarti lebih banyak server, lebih banyak biaya.

Contoh Kode: Mengirim dan Menerima Event dengan Kafka (Node.js)

// producer.js — Mengirim event ke Kafka
const { Kafka } = require('kafkajs');

const kafka = new Kafka({
  clientId: 'order-service',
  brokers: ['localhost:9092'],
});

async function sendEvent() {
  const producer = kafka.producer();
  await producer.connect();

  const event = {
    eventType: 'ORDER_CREATED',
    orderId: 'ORD-2026-001',
    product: 'Laptop ASUS ROG',
    quantity: 1,
    timestamp: new Date().toISOString(),
  };

  await producer.send({
    topic: 'order-events',
    messages: [
      {
        key: 'ORD-2026-001', // key menentukan partisi
        value: JSON.stringify(event),
        headers: {
          'event-type': 'ORDER_CREATED',
          'source': 'order-service',
        },
      },
    ],
  });

  console.log(`[Producer] Event terkirim: ${event.eventType}`);
  await producer.disconnect();
}

sendEvent();
// consumer.js — Menerima event dari Kafka
const { Kafka } = require('kafkajs');

const kafka = new Kafka({
  clientId: 'notification-service',
  brokers: ['localhost:9092'],
});

async function consumeEvents() {
  const consumer = kafka.consumer({ groupId: 'notification-group' });
  await consumer.connect();
  await consumer.subscribe({ topic: 'order-events', fromBeginning: false });

  console.log('[Consumer] Menunggu event...');

  await consumer.run({
    eachMessage: async ({ topic, partition, message }) => {
      const event = JSON.parse(message.value.toString());
      console.log(`[Consumer] Event diterima: ${event.eventType}`);
      console.log(`  Order: ${event.orderId} | Partition: ${partition}`);
      console.log(`  Offset: ${message.offset}`);

      // Proses event (misalnya: kirim notifikasi)
    },
  });
}

consumeEvents();

Perhatikan bedanya dengan RabbitMQ: di Kafka, nggak ada konsep “acknowledge per message”. Consumer commit offset-nya sendiri. Dan fromBeginning: false artinya consumer baru cuma baca event yang masuk setelah dia subscribe — tapi kalau kamu set true, dia bisa baca semua dari awal. Ini yang dimaksud dengan “replay capability”.


Perbandingan Langsung: RabbitMQ vs Kafka

Oke, sekarang kita udah kenal keduanya. Saatnya lihat perbandingan langsung biar makin jelas:

AspekRabbitMQKafka
TipeTraditional message brokerDistributed event streaming platform
ModelQueue-based (push)Log-based (pull)
ThroughputRatusan ribu msg/detikJutaan msg/detik
LatensiSub-millisecondLow millisecond
Message retentionHapus setelah ackTetap sampai TTL habis
ReplayTidak nativeYa, built-in
RoutingSangat fleksibel (exchange)Berdasarkan partition & key
OrderingPer queuePer partition
ProtokolAMQP, MQTT, STOMPKafka Protocol (binary)
KompleksitasSedangTinggi
Best forTask distribution, RPC, routing kompleksEvent sourcing, log aggregation, stream processing
DurabilitasOpsional (durable queue + persistent msg)Default tinggi (replicated log)

Satu hal yang sering bikin orang salah paham: Kafka dan RabbitMQ bukan pengganti satu sama lain. Mereka solve problem yang berbeda. Membandingkan mereka tanpa konteks itu kayak membandingkan pisau bedah dengan gergaji — keduanya tajam, tapi fungsinya beda.


Kapan Harus Pakai RabbitMQ?

Setelah pakai keduanya di production, berikut ini situasi di mana menurut gue RabbitMQ adalah pilihan yang lebih tepat:

1. Task Queue / Background Jobs

Ini use case klasik RabbitMQ. Kamu punya web app yang perlu kirim email, generate PDF, resize gambar, atau proses pembayaran — tapi nggak mau bikin user nunggu. Masukkan tugas ke queue, dan worker di belakang yang proses.

[Web App] → [RabbitMQ: email_queue] → [Worker 1, Worker 2, Worker 3]

Dengan prefetch dan multiple consumer, kamu bisa scale worker sesuai kebutuhan.

2. Routing Kompleks

Butuh kirim event “user.registered” ke service email, service analytics, dan service CRM sekaligus? Atau mau kirim ke queue tertentu berdasarkan tipe user (premium vs free)? RabbitMQ dengan topic exchange dan binding patterns bikin ini jadi sangat mudah.

3. Request-Reply Pattern (RPC)

RabbitMQ mendukung pattern RPC secara natural. Producer bisa menunggu reply dari consumer lewat temporary queue. Ini berguna untuk integrasi antar service yang butuh response.

4. Protokol Beragam

Kalau kamu punya IoT devices yang pakai MQTT, legacy systems yang pakai STOMP, dan modern services yang pakai AMQP — RabbitMQ bisa handle semuanya lewat plugin.

5. Tim Kecil, Project Baru

Jujur, kalau kamu masih di fase early stage atau timnya kecil, RabbitMQ jauh lebih mudah di-setup dan di-maintain. Docker-compose satu file, management UI langsung jalan, dan learning curve-nya nggak terlalu curam.


Kapan Harus Pakai Kafka?

Sekarang, kapan Kafka adalah pilihan yang tepat?

1. Event Sourcing & Event-Driven Architecture

Kalau arsitektur kamu berbasis event — di mana setiap perubahan state dicatat sebagai event — Kafka adalah jawabannya. Kamu bisa rebuild state kapan saja dengan me-replay semua event dari awal.

2. Log Aggregation & Data Pipeline

Punya 50 microservices yang masing-masing nge-log? Kirim semua log ke Kafka, lalu stream ke Elasticsearch, S3, atau data warehouse. Kafka dibangun persis untuk use case kayak gini.

3. High-Throughput Real-Time Processing

Kalau kamu perlu memproses jutaan event per detik — misalnya clickstream analytics, sensor data, financial transactions — Kafka bisa handle itu tanpa berkeringat.

4. Multiple Consumer Independen

Di RabbitMQ, kalau satu pesan di-consume, dia hilang dari queue. Kalau kamu butuh 5 service berbeda memproses pesan yang sama secara independen? Di Kafka ini sangat natural — setiap service punya consumer group sendiri dan bisa baca dari offset-nya masing-masing.

5. Audit Trail & Compliance

Karena data Kafka tersimpan untuk periode tertentu (bisa hari, minggu, bahkan selamanya), kamu punya audit trail yang sangat berguna untuk compliance, debugging, atau forensic analysis.


Tips dari Pengalaman: Hal yang Sering Terlewat

Setelah ngulik keduanya di production, ada beberapa pelajaran yang gue dapet (kebanyakan dari kesalahan sendiri):

RabbitMQ

  • Selalu set durable dan persistent. Tanpa ini, pesan hilang kalau RabbitMQ restart. Gue pernah kehilangan ratusan task gara-gara lupa ini.
  • Gunakan DLX (Dead Letter Exchange). Kalau pesan gagal diproses berkali-kali, jangan biarkan dia nongol terus di queue utama. Kirim ke dead letter queue, handle nanti.
  • Monitor queue depth. Kalau queue terus membesar, artinya consumer nggak sanggup. Ini sinyal untuk scale up.
  • Hati-hati dengan auto-ack. Jangan pakai auto-acknowledge kecuali kamu benar-benar yakin pesan nggak akan hilang.

Kafka

  • Pilih jumlah partition dengan hati-hati. Terlalu sedikit = bottleneck. Terlalu banyak = overhead. Aturan thumb: partition = jumlah max consumer yang kamu butuhkan.
  • Perhatikan retention.ms dan retention.bytes. Default-nya 7 hari. Kalau disk terbatas, sesuaikan.
  • Handle rebalancing dengan graceful shutdown. Kalau consumer mati mendadak, rebalance bisa trigger duplikasi. Gunakan session.timeout.ms dan heartbeat.interval.ms dengan bijak.
  • Gunakan key yang tepat. Key di Kafka bukan sekadar identifier — dia menentukan partisi. Kalau kamu butuh ordering per user, pakai userId sebagai key.
  • Jangan underestimate operational cost. Kafka butuh monitoring yang serius. Gunakan tools seperti Confluent Control Center, Burrow, atau Grafana + Prometheus.

Bisa Pakai Keduanya Sekaligus?

Absolutely. Dan ini sebenarnya pattern yang cukup umum di arsitektur yang besar.

Misalnya:

  • RabbitMQ untuk task queue internal (kirim email, generate report, dll.)
  • Kafka untuk event streaming antar domain (order events, payment events, user activity logs)

Masing-masing dipakai untuk use case yang paling dia kuasai. Nggak ada aturan yang bilang kamu harus pilih salah satu.

Beberapa perusahaan besar bahkan pakai keduanya bersama: RabbitMQ sebagai “frontend” message broker yang menerima request dari berbagai sumber, lalu meneruskannya ke Kafka untuk di-stream dan di-proses secara batch.


Ringkasan: Decision Framework

Kalau kamu masih bingung, coba tanyakan pertanyaan ini ke diri sendiri:

  1. Apakah kamu butuh message routing yang kompleks? → RabbitMQ
  2. Apakah kamu butuh throughput jutaan msg/detik? → Kafka
  3. Apakah kamu butuh replay event? → Kafka
  4. Apakah ini untuk task queue / background jobs? → RabbitMQ
  5. Apakah kamu butuh event sourcing / event-driven architecture? → Kafka
  6. Apakah tim kamu kecil dan butuh setup yang cepat? → RabbitMQ
  7. Apakah kamu butuh data pipeline real-time? → Kafka
  8. Apakah kamu butuh protocol selain HTTP (MQTT, STOMP)? → RabbitMQ

Kalau sebagian besar jawabannya ke kiri, pakai RabbitMQ. Kalau ke kanan, pakai Kafka. Kalau campuran, pertimbangkan pakai keduanya.


Masih Bingung? Kita Ngobrol Yuk!

Kalau kamu udah baca sampai sini dan masih bingung menentukan mana yang cocok untuk project spesifik kamu — nggak apa-apa, wajar kok. Setiap project punya konteks yang unik, dan kadang butuh diskusi lebih dalam untuk bikin keputusan yang tepat.

Jangan ragu buat reach out ke gue di [email protected]. Ceritakan case kamu, dan kita bisa diskusi bareng solusi yang paling masuk akal. Nggak ada pertanyaan yang terlalu kecil atau terlalu besar.


FAQ: Pertanyaan yang Sering Ditanyakan

1. Apakah Kafka bisa menggantikan RabbitMQ sepenuhnya?

Secara teknis, kamu bisa memaksa Kafka untuk melakukan pekerjaan RabbitMQ. Tapi hasilnya nggak optimal. Kafka nggak punya fitur routing sefleksibel RabbitMQ, nggak punya DLX, dan overhead-nya terlalu besar untuk use case sederhana kayak task queue. Lebih baik pakai masing-masing untuk apa yang dia kuasai.

2. Berapa biaya minimum untuk menjalankan Kafka di production?

Ini tergantung provider dan skala. Kalau self-hosted, kamu butuh minimal 3 broker (idealnya bare metal atau VM dengan RAM 16GB+ dan SSD). Kalau pakai managed service seperti Confluent Cloud atau AWS MSK, biaya mulai dari sekitar $200-500/bulan untuk cluster kecil. Tapi ingat, Kafka juga butuh monitoring dan maintenance — itu biaya yang sering nggak terhitung.

3. Saya baru mulai belajar message queue, mana yang sebaiknya saya pelajari duluan?

Mulai dari RabbitMQ. Konsepnya lebih intuitif dan lebih dekat dengan mental model “queue” yang biasa kita kenal. Setelah kamu paham fundamental messaging (producer, consumer, acknowledgment, routing), baru lanjut ke Kafka. Transisi akan jauh lebih mudah karena kamu sudah punya dasar yang kuat.

4. Apakah ada alternatif lain selain RabbitMQ dan Kafka?

Tentu. Ada beberapa opsi yang layak dipertimbangkan:

  • NATS: Sangat ringan dan cepat, cocok untuk microservices.
  • Redis Streams: Kalau kamu sudah pakai Redis, fitur streams-nya cukup powerful.
  • Amazon SQS/SNS: Managed service dari AWS, zero operational overhead.
  • Apache Pulsar: Mirip Kafka tapi dengan fitur multi-tenancy dan tiered storage.
  • ZeroMQ: Untuk yang butuh messaging tanpa broker (brokerless).

Pilihan tergantung kebutuhan, infrastruktur yang ada, dan kemampuan tim