# Arsitektur Event-Driven Berbasis Kafka untuk Real-Time Data Streaming

> Diterbitkan oleh Literally Web ID pada 21 Oct 2026
> Sumber: https://literally.web.id/articles/arsitektur-event-driven-berbasis-kafka-untuk-real-time-data-streaming

---

Dalam 15 menit ke depan, kita akan merakit sebuah stack event-driven berbasis Apache Kafka dari nol sampai berjalan mulus di atas infrastruktur kita, mirip seperti meracik hidangan utama di dapur resto bintang lima saat jam makan malam.

## 1. Menu Kita Hari Ini & Alat yang Perlu Disiapkan
Pernahkah Anda mendapati database MySQL di backend web Anda megap-megap karena ribuan request masuk secara bersamaan saat flash sale? Dulu, saya sering begadang semalaman gara-gara koneksi PHP-FPM dan Nginx kolaps akibat lonjakan trafik instan. Solusinya bukan sekadar menambah RAM, melainkan mengubah cara kita mengalirkan data menggunakan arsitektur event-driven.

Hari ini, kita tidak akan membahas teori abstrak tentang antrean pesan. Kita akan langsung membangun pipa data real-time menggunakan Apache Kafka bersama ZooKeeper (atau KRaft), didukung oleh backend Node.js atau Go, serta memonitor consumer lag secara langsung.

> [!IMPORTANT]
> Pastikan Anda telah menyiapkan mesin virtual berbasis Linux (Ubuntu 22.04 LTS direkomendasikan) dengan minimal 4GB RAM, Docker, dan Docker Compose terpasang agar proses simulasi cluster Kafka berjalan tanpa hambatan.

Sebelum kita menyalakan mesin, mari kita petakan dulu apa sebenarnya bentuk arsitektur yang sedang kita bangun agar setiap baris kode yang kita ketik memiliki arah yang jelas...

## 2. Peta Jalan Singkat: Apa yang Sedang Kita Rakit
Bayangkan Kafka sebagai sistem pipa air raksasa di kota metropolitan. Produsen air (web service, microservices berbasis Go/Node, atau webhook payment gateway) memompa data event ke dalam 'Topic'. Di sisi lain, para konsumen (layanan analitik, worker pengirim email via Postfix, atau sinkronisasi ke Redis) menyedot data tersebut melalui 'Consumer Groups'.

Dalam resep kali ini, langkah kerja kita sangat terstruktur:
1. Menyiapkan Docker Compose untuk menjalankan cluster Kafka dan Zookeeper.
2. Mengonfigurasi Kafka Topics dengan strategi **Partitioning dan Offset** yang tepat agar paralelisme tercapai maksimal.
3. Menulis script produsen dan konsumen untuk menguji **Consumer Lag** dan bagaimana sistem melakukan penyeimbangan beban (rebalancing).
4. Mengatur **Fault Tolerance dan Replication Factor** agar sistem tetap hidup meskipun salah satu node server kita tumbang mendadak.

Tanpa berlama-lama lagi, mari kita buka terminal dan mulai merakit fondasinya.

## 3. Langkah 1: Mempersiapkan Fondasi & Environment
Langkah awal yang paling krusial adalah memastikan infrastruktur dasar kita berdiri kokoh. Kita akan menggunakan Docker Compose untuk mendeploy Apache Kafka dan Zookeeper dalam satu jaringan bridge yang terisolasi.

Buat file bernama `docker-compose.yml` di direktori kerja Anda, lalu masukkan konfigurasi berikut:

```yaml
version: '3.8'

services:
  zookeeper:
    image: confluentinc/cp-zookeeper:7.5.0
    container_name: zookeeper
    environment:
      ZOOKEEPER_CLIENT_PORT: 2181
      ZOOKEEPER_TICK_TIME: 2000
    networks:
      - kafka-net

  kafka:
    image: confluentinc/cp-kafka:7.5.0
    container_name: kafka
    depends_on:
      - zookeeper
    ports:
      - "9092:9092"
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_ZOOKEEPER_CONNECT: 'zookeeper:2181'
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092,PLAINTEXT_HOST://localhost:29092
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
      KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
      KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
      KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
    networks:
      - kafka-net

networks:
  kafka-net:
    driver: bridge
```

Jalankan perintah ini di terminal untuk menghidupkan stack:
```bash
docker-compose up -d
```

Perhatikan respons di layar Anda. Jika container `zookeeper` dan `kafka` mengeluarkan status `Started` atau `Healthy`, itu tanda bahwa fondasi kita sudah siap menerima aliran data pertama.

Dari fondasi container ini, kita sekarang melangkah ke jantung utama Kafka: bagaimana data diorganisasikan melalui topik, partisi, dan offset.

## 4. Langkah 2: Meracik Konfigurasi Inti Tanpa Basa-basi
Di sinilah keajaiban event-streaming terjadi. Kita akan membuat sebuah Kafka Topic bernama `user-activity-stream` dengan 3 partisi. Mengapa 3 partisi? Karena ini memungkinkan kita mendistribusikan beban kerja ke beberapa consumer secara paralel.

Masuk ke dalam container Kafka untuk mengeksekusi CLI tool bawaan:
```bash
docker exec -it kafka kafka-topics --create \
  --bootstrap-server localhost:9092 \
  --replication-factor 1 \
  --partitions 3 \
  --topic user-activity-stream
```

Untuk memverifikasi bahwa topik berhasil dibuat beserta pembagian partisinya, jalankan perintah deskripsi ini:
```bash
docker exec -it kafka kafka-topics --describe \
  --bootstrap-server localhost:9092 \
  --topic user-activity-stream
```

> [!TIP]
> **Konsep Partitioning dan Offset:** Setiap pesan yang masuk ke partisi akan diberi penomoran urut unik yang disebut *Offset*. Offset inilah yang bertindak sebagai 'bookmark' bagi consumer. Jika consumer kita mendadak restart, ia tidak akan membaca ulang data dari awal, melainkan melanjutkan dari offset terakhir yang telah dikomit (committed offset).

Namun, apa yang terjadi jika jumlah pesan yang masuk jauh lebih cepat daripada kecepatan consumer memprosesnya? Mari kita bahas mekanisme penyelamatannya di bagian berikutnya.

## 5. Langkah 3: Sentuhan Akhir Keamanan & Optimasi
Masalah klasik di lapangan adalah **Consumer Lag**—selisih antara pesan terakhir yang masuk ke partisi dengan pesan terakhir yang berhasil dibaca oleh consumer group. Jika lag ini menumpuk, antrean akan membengkak dan sistem real-time kita akan terasa lambat.

Untuk mengatasinya, kita pastikan consumer diatur dalam satu Consumer Group yang sama agar Kafka secara otomatis membagi partisi (rebalancing) ke setiap worker instance.

Selain itu, kita juga harus memikirkan **Fault Tolerance dan Replication Factor**. Di lingkungan production, `replication-factor` minimal harus diset ke `3` agar jika satu broker mati, data tetap aman di broker cadangan (In-Sync Replicas / ISR).

Mari kita buat sebuah consumer sederhana menggunakan Node.js untuk melihat bagaimana offset dikelola secara otomatis. Buat file `consumer.js`:

```javascript
const { Kafka } = require('kafkajs');

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

const consumer = kafka.consumer({ groupId: 'activity-reader-group' });

const run = async () => {
  await consumer.connect();
  await consumer.subscribe({ topic: 'user-activity-stream', fromBeginning: true });

  await consumer.run({
    eachMessage: async ({ topic, partition, message }) => {
      console.log({
        partition,
        offset: message.offset,
        value: message.value.toString(),
      });
    },
  });
};

run().catch(console.error);
```

Install dependency dengan `npm install kafkajs`, lalu jalankan consumer tersebut. Sekarang, mari kita uji performa sistem yang sudah kita racik ini.

## 6. Tes Rasa: Memastikan Semuanya Berjalan SempurnaUntuk membuktikan bahwa pipa data kita berfungsi secara real-time, kita akan mengirim pesan (produce) langsung ke topik menggunakan CLI Kafka, lalu lihat bagaimana script Node.js kita menyedot pesan tersebut seketika.

Buka terminal baru dan jalankan producer interaktif:
```bash
docker exec -it kafka kafka-console-producer \
  --bootstrap-server localhost:9092 \
  --topic user-activity-stream
```

Ketikkan beberapa kalimat acak, misalnya:
```text
{"user_id": 101, "action": "login\