Message Contract #

Dalam sistem berbasis RabbitMQ, message sering dianggap hanya sebagai payload JSON biasa.

Padahal secara arsitektural, message adalah:

  • Kontrak antar service
  • API asynchronous
  • Representasi fakta bisnis

Kesalahan dalam mendesain message contract dapat menyebabkan:

  • Breaking change antar service
  • DLQ meningkat tiba-tiba
  • Retry storm
  • Ketergantungan implisit yang tidak terdokumentasi

Karena itu, message contract harus diperlakukan dengan disiplin yang sama seperti API HTTP publik.

“Event yang dikirim hari ini bisa menjadi fondasi sistem bertahun-tahun ke depan — atau menjadi sumber kerusakan yang tidak pernah selesai.”

Apa Itu Message Contract? #

Message contract adalah definisi formal mengenai:

  • Nama event
  • Routing key
  • Struktur payload
  • Field wajib dan opsional
  • Tipe data
  • Versi
  • Ownership

Ia menjawab pertanyaan:

“Apa yang boleh dan tidak boleh ada dalam message ini?”

Tanpa kontrak yang jelas, integrasi antar service menjadi rapuh.


Mengapa Message Contract Sangat Penting di RabbitMQ? #

Berbeda dengan REST API:

  • Tidak ada schema validation otomatis
  • Tidak ada HTTP status code
  • Tidak ada OpenAPI default

Jika producer mengubah struktur payload tanpa koordinasi:

  • Consumer bisa crash
  • Message masuk DLQ
  • Sistem terhenti sebagian

Dalam sistem asynchronous, kesalahan sering terlihat terlambat.


Elemen Penting dalam Message Contract #

1️⃣ Naming Convention Event #

Gunakan pola konsisten, misalnya:

  • order.created
  • payment.completed
  • user.registered

Hindari nama ambigu seperti:

  • process
  • update
  • event1

Nama event adalah identitas domain.


2️⃣ Struktur Payload yang Jelas #

Tentukan:

  • Field wajib
  • Field opsional
  • Tipe data
  • Format tanggal (ISO 8601)
  • Enum yang diperbolehkan

Contoh:

{
  "event_id": "uuid",
  "event_version": 1,
  "occurred_at": "2026-02-20T10:00:00Z",
  "order_id": "string",
  "status": "CREATED"
}

Struktur harus terdokumentasi.


3️⃣ Versioning Strategy #

Schema akan berubah.

Pertanyaannya bukan apakah berubah, tetapi kapan.

Strategi umum:

  • Tambahkan field baru (backward compatible)
  • Hindari menghapus field lama
  • Gunakan event_version
  • Gunakan routing key versioned jika perlu

Contoh:

  • order.created.v1
  • order.created.v2

Backward compatibility adalah kunci stabilitas.


4️⃣ Ownership Jelas #

Setiap event harus memiliki:

  • Producer owner
  • Domain owner

Jika tidak jelas siapa pemilik kontrak, perubahan menjadi tidak terkontrol.


5️⃣ Idempotency Awareness #

Karena RabbitMQ default adalah at-least-once delivery:

  • Duplicate message bisa terjadi

Message contract harus mengandung identifier unik seperti:

  • event_id
  • order_id
  • correlation_id

Consumer harus mampu mendeteksi duplicate.


Anti-Pattern dalam Message Contract #

Beberapa kesalahan umum:

  • Mengirim seluruh entity database apa adanya
  • Mengubah struktur payload tanpa versioning
  • Menghapus field lama secara tiba-tiba
  • Tidak mendokumentasikan event
  • Menggunakan field ambigu

Message contract yang tidak disiplin adalah sumber integrasi yang rapuh.


Message Contract dan DLQ #

Banyak message masuk DLQ karena:

  • Field hilang
  • Tipe berubah
  • Enum tidak dikenali

DLQ sering kali adalah indikator bahwa kontrak tidak dikelola dengan baik.

Monitoring DLQ dapat menjadi alarm perubahan kontrak yang tidak kompatibel.


Dokumentasi dan Validasi #

Beberapa pendekatan yang bisa digunakan:

  • JSON Schema
  • Avro
  • Protobuf
  • Internal contract registry

Validasi bisa dilakukan:

  • Di sisi producer sebelum publish
  • Di sisi consumer sebelum proses

Schema validation mengurangi kesalahan runtime.


Perbandingan: Tanpa vs Dengan Contract Discipline #

Tanpa Kontrak JelasDengan Kontrak Jelas
Breaking change seringStabil jangka panjang
DLQ meningkat tiba-tibaError terkontrol
Integrasi sulitIntegrasi predictable
Coupling implisitBoundary jelas

Kontrak adalah boundary antar service.


Prinsip Message Contract yang Sehat #

  • Treat event as public API
  • Hindari breaking change
  • Version dengan disiplin
  • Dokumentasikan payload
  • Gunakan identifier unik
  • Monitor DLQ sebagai indikator kontrak rusak

Messaging tanpa kontrak adalah integrasi tanpa pagar.


Ringkasan #

Message contract menentukan:

  • Stabilitas antar service
  • Kejelasan domain
  • Ketahanan terhadap perubahan
  • Kemudahan scaling tim

Ia bukan detail kecil. Ia adalah fondasi arsitektur asynchronous.


Penutup #

RabbitMQ memindahkan pesan.

Tetapi pesan itu sendiri membawa makna bisnis.

Jika makna tersebut tidak didefinisikan dengan jelas, sistem akan rapuh terhadap perubahan.

Message contract adalah janji antar service.

Janji itu harus dijaga dengan disiplin, versioning yang matang, dan dokumentasi yang jelas.

Karena dalam sistem terdistribusi, kegagalan sering kali bukan karena jaringan putus.

Tetapi karena kontrak yang dilanggar tanpa disadari.

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact