Engineering
Apache Kafka untuk Arsitektur Microservices: Panduan Lengkap Event-Driven Architecture
Pelajari cara membangun arsitektur microservices yang scalable dengan Apache Kafka. Panduan lengkap event-driven architecture, async communication, dan best practices 2026.
Microservices membuat aplikasi lebih modular, tapi juga menciptakan masalah baru: bagaimana ratusan service berkomunikasi tanpa saling menunggu? Apache Kafka hadir sebagai event backbone yang menyelesaikan masalah ini — bukan sekadar message queue, tapi distributed event streaming platform yang bisa memproses jutaan event per detik.
Apache Kafka: event streaming platform untuk microservices modern
Butuh contoh event-driven architecture yang lebih detail? Baca juga panduan lengkap Redis Streams untuk developer Indonesia — alternatif ringan untuk use case tertentu. Jika Anda sedang membangun data pipeline end-to-end, simak juga cara membangun data pipeline yang tidak pernah tidur.
2. Mengapa Microservices Butuh Event Backbone?
Bayangkan sebuah e-commerce dengan 50 microservices. Ketika user checkout, service order harus memberi tahu service inventory, payment, shipping, notification, dan analytics. Jika semua komunikasi dilakukan langsung (synchronous), satu service yang lambat akan memblokir seluruh alur. Inilah yang disebut cascading failure.
Kafka menyelesaikan masalah ini dengan pendekatan event-driven architecture. Alih-alih service A memanggil service B secara langsung, service A cukup mempublish event ke Kafka. Service B, C, D — dan service manapun yang butuh data itu — tinggal subscribe ke topic yang sama. Tidak ada coupling langsung antar service.
3. Arsitektur Kafka: Komponen yang Harus Dipahami
Sebelum masuk ke implementasi, pahami dulu komponen utama Kafka:
Arsitektur microservices membutuhkan komunikasi yang reliable antar service
Broker dan Cluster
Broker adalah server Kafka yang menyimpan data. Sebuah cluster terdiri dari minimal 3 broker untuk fault tolerance. Kafka versi 4.0 (rilis Maret 2025) menggunakan KRaft mode — menghapus ketergantungan pada ZooKeeper dan menggantinya dengan protocol Raft bawaan. Ini membuat arsitektur lebih sederhana dan lebih cepat.
Topic dan Partition
Topic adalah kategori message. Setiap topic dibagi menjadi partitions — unit dasar parallelisme Kafka. Partition berisi urutan message yang tidak berubah (immutable log). Semakin banyak partition, semakin tinggi throughput yang bisa dicapai.
Producer dan Consumer
Producer mengirim event ke topic tertentu. Consumer membaca event dari topic. Yang menarik, consumer bisa membaca dari posisi manapun di log — bisa dari awal, dari 1 jam lalu, atau dari posisi terakhir. Ini memungkinkan event replay, fitur yang tidak dimiliki message queue tradisional.
Consumer Group
Consumer group memungkinkan parallel processing. Jika sebuah topic punya 6 partition dan consumer group punya 3 consumer, setiap consumer akan membaca 2 partition secara paralel. Tambah consumer? Throughput naik tanpa mengubah kode.
Replica
Setiap partition direplikasi ke beberapa broker. Satu replica ditandai sebagai leader (melayani read/write), sisanya follower. Jika leader mati, follower otomatis mengambil alih. Data tidak pernah hilang selama minimal 1 replica hidup.
4. Pola Komunikasi Microservices dengan Kafka
Kafka bukan cuma "kirim pesan". Ada beberapa pola arsitektural yang menjadi fondasi microservices modern:
Event Notification
Pola paling sederhana. Ketika service A melakukan sesuatu, ia mempublish event. Service lain tinggal subscribe. Contoh: ketika order dibuat, publish event OrderCreated. Service inventory, payment, dan notification masing-masing subscribe dan memproses sesuai kebutuhan.
Event-Carried State Transfer
Event membawa data yang cukup lengkap, bukan cuma ID. Service consumer tidak perlu memanggil balik service producer untuk mendapatkan data. Ini mengurangi inter-service calls secara drastis.
Saga Pattern
Untuk transaksi yang melibatkan beberapa service, saga pattern memecah transaksi besar menjadi sequence of local transactions. Setiap step mempublish event yang memicu step berikutnya. Jika gagal, compensating events dibuat untuk membatalkan step sebelumnya.
PaymentInitiated → PaymentService proses → publish PaymentCompleted → InventoryService kurangi stok → publish StockReserved. Jika PaymentService gagal, publish PaymentFailed → OrderService batalkan order.
CQRS (Command Query Responsibility Segregation)
Memisahkan model write (command) dan read (query). Write model menyimpan data di database utama, lalu mempublish event ke Kafka. Read model subscribe event dan membangun view/aggregate sendiri yang dioptimasi untuk query tertentu. Hasilnya: write dan read bisa di-scale secara independen.
Change Data Capture (CDC)
Menggunakan Kafka Connect dengan Debezium connector untuk mereplikasi perubahan database secara real-time ke Kafka. Ketika ada INSERT, UPDATE, atau DELETE di database, perubahan itu otomatis menjadi event di Kafka. Service lain bisa subscribe tanpa perlu mengakses database langsung.
Message queue memungkinkan komunikasi asynchronous antar service
// Advertisement
5. Kafka vs RabbitMQ vs Pulsar vs Kinesis
Memilih message broker untuk microservices bukan keputusan sepele. Berikut perbandingan yang jujur:
| Fitur | Apache Kafka | RabbitMQ | Apache Pulsar | Amazon Kinesis |
|---|---|---|---|---|
| Throughput | 1M+ msg/sec | ~50K msg/sec | 1M+ msg/sec | ~1M msg/sec |
| Lateni | Sub-millisecond | Low | Sub-millisecond | Low-medium |
| Persistence | ✅ Disk-based log | ⚠️ Queue-based | ✅ Tiered storage | ✅ 24 jam default |
| Replay | ✅ Full replay | ❌ Tidak ada | ✅ Full replay | ⚠️ 24 jam saja |
| Consumer Group | ✅ Native | ✅ Competing consumers | ✅ Native | ✅ Enhanced fan-out |
| Ordering | ✅ Per-partition | ⚠️ Per-queue | ✅ Per-partition | ✅ Per-shard |
| Ecosystem | ✅ Connect, Streams, ksqlDB | ⚠️ Plugins | ✅ Functions, IO | ⚠️ AWS only |
| Ops Complexity | ⚠️ Medium-high | ✅ Low-medium | ❌ High | ✅ Managed |
| Vendor Lock-in | ✅ Open source | ✅ Open source | ✅ Open source | ❌ AWS only |
6. Setup Kafka untuk Microservices
Mulai dari Docker Compose untuk development. Konfigurasi ini menggunakan KRaft mode (tanpa ZooKeeper):
Docker Compose untuk Kafka
# docker-compose.yml
version: '3.8'
services:
kafka:
image: apache/kafka:3.9.0
container_name: kafka-broker
ports:
- "9092:9092"
environment:
KAFKA_NODE_ID: 1
KAFKA_PROCESS_ROLES: broker,controller
KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092
KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT
KAFKA_CONTROLLER_QUORUM_VOTERS: 1@kafka:9093
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
KAFKA_LOG_DIRS: /tmp/kraft-combined-logs
CLUSTER_ID: 'MkU3OEVBNTcwNTJENDM2Qk'
Producer Microservice (Java)
// OrderService.java - Publish event saat order dibuat
import org.apache.kafka.clients.producer.*;
import org.apache.kafka.common.serialization.StringSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
public class OrderService {
private final KafkaProducer<String, String> producer;
private final ObjectMapper mapper = new ObjectMapper();
public OrderService() {
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("key.serializer", StringSerializer.class.getName());
props.put("value.serializer", StringSerializer.class.getName());
props.put("acks", "all");
props.put("enable.idempotence", true); // exactly-once delivery
this.producer = new KafkaProducer<>(props);
}
public void createOrder(Order order) throws Exception {
// Simpan order ke database...
// Publish event ke Kafka
OrderEvent event = new OrderEvent("OrderCreated", order.getId(),
order.getUserId(), order.getItems(), Instant.now());
ProducerRecord<String, String> record =
new ProducerRecord<>("orders", order.getId(), mapper.writeValueAsString(event));
producer.send(record, (metadata, exception) -> {
if (exception != null) {
// Handle error, retry atau dead letter queue
System.err.println("Failed to publish OrderCreated: " + exception.getMessage());
} else {
System.out.println("OrderCreated published to " + metadata.topic()
+ " partition " + metadata.partition());
}
});
}
}
Consumer Microservice (Python)
# inventory_service.py - Subscribe ke order events
from kafka import KafkaConsumer
import json
class InventoryService:
def __init__(self):
self.consumer = KafkaConsumer(
'orders',
bootstrap_servers='localhost:9092',
group_id='inventory-service',
auto_offset_reset='earliest',
enable_auto_commit=False, # manual commit untuk at-least-once
value_deserializer=lambda m: json.loads(m.decode('utf-8'))
)
def process_events(self):
print("InventoryService listening to 'orders' topic...")
for message in self.consumer:
event = message.value
print(f"Received event type: {event['type']}")
if event['type'] == 'OrderCreated':
self.reserve_stock(event['payload']['items'])
elif event['type'] == 'OrderCancelled':
self.release_stock(event['payload']['items'])
# Manual commit setelah proses berhasil
self.consumer.commit()
def reserve_stock(self, items):
for item in items:
# Kurangi stok di database...
print(f"Reserved {item['quantity']}x {item['name']}")
print("Stock reserved successfully")
if __name__ == '__main__':
service = InventoryService()
service.process_events()
Kafka CLI Commands
# Buat topic baru
bin/kafka-topics.sh --create \
--topic orders \
--bootstrap-server localhost:9092 \
--partitions 6 \
--replication-factor 3
# Lihat daftar topic
bin/kafka-topics.sh --list --bootstrap-server localhost:9092
# Lihat detail topic
bin/kafka-topics.sh --describe --topic orders --bootstrap-server localhost:9092
# Test kirim message dari CLI
bin/kafka-console-producer.sh --topic orders --bootstrap-server localhost:9092
# Test baca message dari CLI
bin/kafka-console-consumer.sh --topic orders --bootstrap-server localhost:9092 \
--from-beginning --group test-consumer
# Cek consumer lag
bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 \
--describe --group inventory-service
7. Ekosistem Kafka: Lebih dari Sekadar Broker
Kafka bukan cuma message broker. Ekosistemnya punya tools kuat untuk microservices:
Data pipeline modern memanfaatkan streaming untuk real-time processing
Kafka Connect
Framework untuk integrasi data dari/to sistem eksternal tanpa menulis kode custom. Tersedia ratusan connector: PostgreSQL, MongoDB, Elasticsearch, S3, dan banyak lagi. Untuk CDC, gunakan Debezium connector yang mereplikasi perubahan database ke Kafka secara real-time.
Kafka Streams
Java library untuk stream processing. Tidak perlu cluster terpisah — berjalan sebagai bagian dari aplikasi microservice. Cocok untuk aggregasi, filtering, join, dan transformasi data secara real-time.
// Contoh Kafka Streams: Aggregasi order per user
import org.apache.kafka.streams.*;
import org.apache.kafka.streams.kstream.*;
Properties props = new Properties();
props.put(StreamsConfig.APPLICATION_ID_CONFIG, "order-aggregation");
props.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
StreamsBuilder builder = new StreamsBuilder();
KStream<String, OrderEvent> orders = builder.stream("orders");
orders.groupByKey()
.windowedBy(TimeWindows.ofSizeWithNoGrace(Duration.ofMinutes(5)))
.count()
.toStream()
.to("order-counts");
ksqlDB
SQL engine untuk query data di Kafka secara real-time. Tidak perlu menulis kode Java atau Python. Contoh: buat materialized view dari order events hanya dengan SQL.
-- Buat stream dari topic orders
CREATE STREAM orders_stream (
event_type VARCHAR KEY,
order_id VARCHAR,
user_id VARCHAR,
total_amount DECIMAL(10,2)
) WITH (
KAFKA_TOPIC = 'orders',
VALUE_FORMAT = 'JSON'
);
-- Agregasi: total order per user dalam 1 jam window
SELECT user_id, COUNT(*) as order_count, SUM(total_amount) as total_spent
FROM orders_stream
WINDOW TUMBLING (SIZE 1 HOUR)
GROUP BY user_id;
Schema Registry
Centralized schema management untuk memastikan producer dan consumer menggunakan format data yang konsisten. Mendukung Avro, Protobuf, dan JSON Schema. Tanpa Schema Registry, perubahan format data bisa memecah consumer secara tiba-tiba.
8. Best Practices untuk Microservices dengan Kafka
Partitioning Strategy
Gunakan message key yang tepat untuk memastikan ordering. Semua event untuk order yang sama harus masuk ke partition yang sama — maka gunakan order_id sebagai key. Jangan gunakan null key (akan di-round-robin, menghilangkan ordering guarantee).
Consumer Group Design
Setiap microservice harus punya consumer group sendiri. Hindari sharing consumer group antar service — ini membuat distribusi message tidak terduga. Jika butuh fan-out (satu event diproses banyak service), setiap service harus punya group ID unik.
// Advertisement
Exactly-Once Semantics
Kafka mendukung exactly-once delivery melalui kombinasi idempotent producer dan transactional API. Untuk microservices, gunakan enable.idempotence=true di producer dan manual offset commit di consumer setelah proses berhasil.
Dead Letter Queue (DLQ)
Jika consumer gagal memproses event setelah N kali retry, kirim ke DLQ topic daripada memblokir seluruh consumer. Ini memastikan satu event yang bermasalah tidak menghentikan seluruh pipeline.
Monitoring Consumer Lag
Consumer lag (selisih antara offset terakhir di partition dan offset yang sudah diproses consumer) adalah metrik kunci. Jika lag terus naik, artinya consumer tidak bisa mengikuti throughput producer. Gunakan Kafka Lag Exporter dengan Prometheus dan Grafana untuk monitoring.
Retention Policy
Atur retention.ms sesuai kebutuhan. Default 7 hari. Untuk microservices yang butuh event replay jangka panjang, pertimbangkan menggunakan tiered storage (tersedia di Kafka 3.7+) untuk archive data lama ke S3/GCS dengan biaya lebih rendah.
9. Studi Kasus: E-Commerce dengan Kafka
Mari lihat bagaimana sebuah e-commerce membangun arsitektur microservices dengan Kafka sebagai backbone:
| Service | Topic yang Dipublish | Topic yang Diasubscribe |
|---|---|---|
| Order Service | orders | payments, inventory |
| Payment Service | payments | orders |
| Inventory Service | inventory | orders |
| Notification Service | notifications | orders, payments |
| Analytics Service | — | orders, payments, inventory, notifications |
| Search Service | — | inventory (via CDC) |
Alur satu transaksi: User checkout → OrderService publish OrderCreated → PaymentService proses payment → publish PaymentCompleted → InventoryService kurangi stok → NotificationService kirim email → AnalyticsService catat transaksi. Semua berjalan asynchronous, tidak ada service yang menunggu service lain.
10. FAQ
Berapa minimum broker yang dibutuhkan untuk production?
Minimal 3 broker untuk fault tolerance. Dengan 3 broker dan replication factor 3, cluster bisa survive jika 1 broker mati tanpa kehilangan data. Untuk throughput tinggi, mulai dari 5-10 broker dan scale sesuai kebutuhan.
Kapan harus pakai Kafka Streams vs Apache Flink?
Kafka Streams cocok untuk transformasi sederhana yang berjalan di dalam microservice — tidak perlu cluster terpisah. Apache Flink dibutuhkan untuk complex event processing, stateful computation skala besar, atau ketika butuh window yang lebih sophisticated. Mulai dari Kafka Streams, migrasi ke Flink jika kebutuhan berkembang.
Bagaimana menangani event yang gagal diproses?
Gunakan retry dengan exponential backoff. Jika tetap gagal setelah N kali percobaan, kirim ke Dead Letter Queue (DLQ) topic. Bangun DLQ consumer yang bisa memanually review dan reprocess event yang bermasalah. Jangan pernah memblokir consumer group karena satu event bermasalah.
Apakah Kafka aman untuk data sensitif?
Kafka mendukung TLS encryption, SASL authentication, dan ACL authorization. Untuk data sensitif (PII, payment data), gunakan encryption in-transit (TLS) dan encryption at-rest. Pertimbangkan juga field-level encryption menggunakan Confluent Schema Registry dengan custom serializer.
Berapa biaya operasional Kafka untuk startup kecil?
Jika di-self-host: 3 VPS minimal (Rp 500K/bulan per VPS) = Rp 1.5 juta/bulan. Jika pakai managed service: Confluent Cloud mulai dari $100/bulan, Amazon MSK mulai dari $0.11/jam. Untuk MVP, pertimbangkan Confluent Cloud atau Aiven untuk mengurangi operational overhead.
Jika Anda membangun stack backend yang mencakup caching dan real-time data, pertimbangkan juga membaca panduan Redis caching patterns untuk scalable web apps sebagai pelengkap arsitektur microservices ini.
Butuh Arsitektur Microservices yang Reliable?
VyuApp membantu Anda membangun sistem event-driven yang scalable dengan pendekatan yang tepat.
Kunjungi VyuApp →Image Attribution
- Photo by Markus Spiske on Unsplash - Unsplash
- Photo by Growtika on Unsplash - Unsplash
- Photo by Samuel Angor on Unsplash - Unsplash
- Photo by Deng Xiang on Unsplash - Unsplash
Referensi
- Apache Kafka Documentation — kafka.apache.org
- Confluent Kafka Documentation — docs.confluent.io
- LinkedIn Engineering Blog: Building Kafka — engineering.linkedin.com
- Red Hat: What is Apache Kafka? — redhat.com
- Debezium Documentation (CDC with Kafka) — debezium.io
// Advertisement
VyuApp Studio
Bespoke web engineering — Garut, ID