Poison Message Handling #

Dalam sistem asynchronous berbasis RabbitMQ, sebagian besar kegagalan bersifat sementara.

Namun ada jenis kegagalan yang lebih berbahaya:

Pesan yang akan selalu gagal, tidak peduli berapa kali dicoba.

Inilah yang disebut Poison Message.

Jika tidak ditangani dengan benar, poison message dapat:

  • Menyebabkan infinite retry loop
  • Menghambat throughput
  • Mengganggu ordering
  • Menghabiskan resource
  • Bahkan melumpuhkan sistem

Artikel ini membahas bagaimana mengenali dan menangani poison message secara arsitektural dalam RabbitMQ.

“Tidak semua pesan gagal karena sistem belum siap — sebagian gagal karena memang tidak bisa diperbaiki.”

Apa Itu Poison Message? #

Poison message adalah message yang:

  • Selalu gagal diproses oleh consumer
  • Tidak akan pernah sukses meskipun dicoba ulang

Contoh kasus:

  • Payload tidak sesuai schema
  • Data corrupt
  • Business rule tidak terpenuhi
  • Referensi data tidak pernah ada

Retry terhadap pesan seperti ini tidak akan membantu.

Ia hanya memperparah masalah.


Bagaimana Poison Message Terjadi? #

Beberapa penyebab umum:

1️⃣ Perubahan Schema Tanpa Backward Compatibility #

Producer mengirim versi baru. Consumer lama tidak bisa memproses.


2️⃣ Data Invalid Permanen #

Contoh:

  • Email kosong
  • ID negatif
  • Field wajib hilang

3️⃣ Bug Logic Bisnis #

Consumer selalu melempar exception untuk tipe data tertentu.


4️⃣ Dependency Tidak Pernah Valid #

Contoh:

  • Order referensi ke produk yang sudah dihapus permanen

Dampak Jika Tidak Ditangani #

Jika poison message terus di-requeue:

  • Consumer terus memproses pesan yang sama
  • Message lain tertahan
  • Throughput turun drastis
  • CPU spike
  • Queue tidak pernah bersih

Ini disebut poison message loop.

Dalam skenario ekstrem, sistem bisa terlihat hidup tetapi tidak memproses pekerjaan nyata.


Strategi Penanganan Poison Message #

Penanganan yang matang biasanya terdiri dari beberapa lapisan.


1️⃣ Batasi Jumlah Retry #

Gunakan header seperti:

  • x-retry-count

Setiap kali message gagal:

  • Tambah retry-count
  • Jika melebihi batas (misal 5 kali) → jangan requeue lagi

Batas retry adalah garis pertahanan pertama.


2️⃣ Gunakan Dead Letter Exchange (DLX) #

Jika retry-count melebihi batas:

  • Nack dengan requeue=false
  • Message masuk ke DLQ permanen

DLQ menjadi tempat isolasi poison message.


3️⃣ Pisahkan Retry Queue dan Final DLQ #

Arsitektur umum:

Main Queue
   |
   v
Retry Queue (TTL + backoff)
   |
   v
Main Exchange

Jika melebihi batas:
   |
   v
Final DLQ

Retry queue untuk error sementara. Final DLQ untuk poison message permanen.


4️⃣ Logging dan Observability #

Poison message tidak boleh diam.

Setiap pesan yang masuk DLQ harus:

  • Dilog
  • Diberi context error
  • Dipantau metric-nya

DLQ depth yang meningkat adalah sinyal ada bug.


5️⃣ Reprocessing Manual atau Terprogram #

DLQ bukan kuburan.

Ia bisa digunakan untuk:

  • Investigasi manual
  • Reprocessing setelah bug diperbaiki
  • Export untuk analisis

Namun reprocessing harus disengaja dan terkendali.


Poison Message vs Transient Failure #

AspekTransient ErrorPoison Message
Retry membantuYaTidak
Cocok untuk backoffYaTidak
Perlu DLQ permanenKadangYa
Dampak jika di-requeue terusRetry stormInfinite loop

Membedakan keduanya adalah tanggung jawab consumer logic.


Deteksi Dini Poison Message #

Beberapa teknik:

  • Validasi schema di awal
  • Gunakan versioned event
  • Gunakan circuit breaker untuk dependency
  • Pisahkan error validation dan error transient

Semakin cepat dideteksi, semakin kecil dampaknya.


Poison Message dalam Quorum Queue #

Pada quorum queue:

  • Poison message tetap direplikasi
  • Tetap konsisten
  • Tetap bisa menyebabkan retry loop

Quorum queue tidak menyelesaikan poison message.

Masalahnya ada di level aplikasi.


Risiko Jika Tidak Ada Strategi #

Tanpa poison message handling:

  • Retry tanpa batas
  • Queue starvation
  • Message lain tertahan
  • SLA gagal
  • Sistem terlihat hidup tetapi tidak produktif

Ini salah satu kegagalan paling berbahaya dalam sistem asynchronous.


Best Practice Production #

  • Selalu batasi retry
  • Pisahkan retry sementara dan DLQ permanen
  • Monitor DLQ depth
  • Tambahkan retry-count header
  • Bedakan error transient vs permanen
  • Audit message schema evolution

Poison message harus dianggap bagian dari desain, bukan kejutan.


Ringkasan #

KonsepPenjelasan
Poison messageMessage yang selalu gagal
Risiko utamaInfinite retry loop
SolusiRetry limit + DLQ
ObservabilityWajib
Root causeBiasanya schema / logic mismatch

Penutup #

Poison message bukan sekadar pesan gagal.

Ia adalah indikator bahwa ada ketidaksesuaian antara kontrak dan implementasi.

Sistem yang matang tidak hanya mampu retry.

Ia mampu mengenali kapan harus berhenti mencoba.

Dalam arsitektur RabbitMQ production, kemampuan mengisolasi poison message sering kali menjadi pembeda antara sistem yang stabil dan sistem yang perlahan runtuh di bawah beban kesalahan yang tak pernah selesai.

Karena tidak semua kegagalan harus dilawan — sebagian harus diisolasi.

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