Exactly-once (Kenapa Sulit di RabbitMQ) #

Dalam diskusi delivery guarantee, banyak orang bertanya:

“Apakah RabbitMQ mendukung exactly-once delivery?”

Jawaban jujurnya:

Tidak secara native.

Namun kita bisa mendesain sistem sehingga efek bisnisnya menjadi exactly-once.

Artikel ini membahas apa itu exactly-once, mengapa ia sulit secara teori dalam sistem terdistribusi, dan bagaimana pendekatan praktisnya di RabbitMQ.

“Exactly-once bukan tentang memastikan pesan hanya dikirim satu kali — tetapi memastikan efeknya hanya terjadi satu kali.”

Apa Itu Exactly-Once Delivery? #

Exactly-once berarti:

  • Message tidak pernah hilang
  • Message tidak pernah diproses dua kali
  • Efek bisnis terjadi tepat satu kali

Secara teori, ini adalah jaminan paling kuat.

Secara praktik, ini sangat sulit dicapai dalam sistem terdistribusi.


Mengapa Exactly-Once Sulit? #

Dalam sistem terdistribusi, kita menghadapi:

  • Network failure
  • Partial crash
  • Timeout
  • Retry
  • Duplicate transmission

Contoh klasik:

1️⃣ Consumer menerima message 2️⃣ Consumer memproses dan update database 3️⃣ Consumer crash sebelum ack 4️⃣ Broker mengirim ulang message

Dari sudut pandang broker:

  • Message belum selesai → dikirim ulang

Dari sudut pandang bisnis:

  • Proses sudah terjadi sekali

Inilah sumber duplicate.


RabbitMQ Secara Default #

RabbitMQ mendukung:

  • At-least-once (manual ack)
  • At-most-once (auto ack)

Tidak ada mekanisme native exactly-once seperti transactional stream processing.

Karena itu, exactly-once harus dibangun di atas at-least-once.


Exactly-Once vs Exactly-Once Effect #

Penting membedakan dua hal:

  • Exactly-once delivery (sangat sulit)
  • Exactly-once effect (realistis)

Kita mungkin tidak bisa mencegah duplicate delivery.

Namun kita bisa memastikan duplicate tidak menghasilkan efek ganda.

Inilah pendekatan praktis.


Strategi Mencapai Exactly-Once Effect #

1️⃣ Idempotent Consumer #

Consumer dirancang agar:

  • Aman dipanggil berulang
  • Tidak menghasilkan efek ganda

Contoh:

  • Update status berdasarkan state machine
  • Gunakan upsert

2️⃣ Unique Event ID + Deduplication #

Setiap message memiliki:

  • event_id (UUID)

Simpan event_id yang sudah diproses di database.

Jika event_id sama muncul lagi → abaikan.

Ini adalah strategi paling umum.


3️⃣ Database Constraint #

Gunakan:

  • Unique constraint
  • Primary key
  • Insert ignore / upsert

Duplicate otomatis ditolak oleh database.

Database menjadi penjaga idempotency.


4️⃣ Transactional Outbox Pattern #

Untuk memastikan publish dan database commit konsisten:

1️⃣ Simpan event di tabel outbox dalam satu transaksi DB 2️⃣ Background worker publish ke RabbitMQ 3️⃣ Tandai sebagai sent

Ini mencegah:

  • Data tersimpan tanpa event
  • Event terkirim tanpa data

Outbox membantu sisi producer.


5️⃣ Consumer Side Transaction + Ack Setelah Commit #

Urutan yang benar:

1️⃣ Mulai DB transaction 2️⃣ Proses event 3️⃣ Commit DB 4️⃣ Kirim ack

Jika crash sebelum commit:

  • Transaction rollback
  • Message dikirim ulang

Jika crash setelah commit sebelum ack:

  • Duplicate mungkin terjadi
  • Tetapi deduplication akan mencegah efek ganda

Perbandingan Delivery Guarantee #

GuaranteeHilang?Duplicate?Kompleksitas
At-Most-OnceBisaTidakRendah
At-Least-OnceTidakBisaSedang
Exactly-Once EffectTidakTidak (efeknya)Tinggi

Exactly-once membutuhkan desain tambahan.


Hubungan dengan Quorum Queue #

Quorum queue:

  • Meningkatkan durability
  • Mengurangi risiko kehilangan data karena node crash

Namun quorum tidak otomatis memberi exactly-once.

Duplicate tetap mungkin terjadi karena faktor aplikasi.


Misconception Umum #

“Jika saya menggunakan quorum dan manual ack, berarti exactly-once.”

Tidak.

Manual ack hanya memberi at-least-once.

Exactly-once membutuhkan idempotency dan deduplication.


Kapan Exactly-Once Effect Penting? #

Sangat penting untuk:

  • Payment processing
  • Financial ledger
  • Inventory stock deduction
  • Critical state machine

Untuk workload non-kritis, at-least-once biasanya cukup.


Ringkasan #

RabbitMQ tidak menyediakan exactly-once delivery native.

Namun kita bisa mencapai exactly-once effect dengan:

  • Idempotent consumer
  • Unique event ID
  • Deduplication storage
  • Database constraint
  • Outbox pattern

Exactly-once adalah hasil desain, bukan fitur konfigurasi.


Penutup #

Dalam sistem terdistribusi, exactly-once delivery murni hampir mustahil tanpa tradeoff besar.

Namun exactly-once effect adalah target realistis yang bisa dicapai dengan disiplin desain.

RabbitMQ memberi fondasi at-least-once.

Sisanya adalah tanggung jawab arsitektur aplikasi.

Karena dalam dunia nyata, bukan jumlah pengiriman yang paling penting.

Tetapi jumlah efek bisnis yang benar-benar terjadi.

Dan arsitektur yang matang memastikan efek itu terjadi tepat sekali.

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