Retry Pattern #

Dalam sistem asynchronous berbasis RabbitMQ, kegagalan adalah hal yang normal.

Namun sistem yang matang tidak hanya mampu mendeteksi kegagalan. Ia harus memiliki strategi retry yang terstruktur.

Retry tanpa desain yang jelas dapat menyebabkan:

  • Infinite retry loop
  • Retry storm
  • CPU spike
  • Dependency overload
  • Queue starvation

Artikel ini membahas berbagai retry pattern dalam RabbitMQ, dari yang sederhana hingga production-grade, lengkap dengan tradeoff dan best practice.

“Retry bukan tentang mencoba lagi secepat mungkin — tetapi tentang mencoba lagi pada waktu yang tepat, dengan batas yang jelas.”

Mengapa Retry Pattern Dibutuhkan? #

Sebagian besar kegagalan dalam sistem terdistribusi bersifat transient:

  • Database timeout
  • Network glitch
  • Service dependency overload
  • Lock contention

Jika tidak dilakukan retry:

  • Message langsung gagal
  • Data bisa hilang

Namun jika retry dilakukan tanpa kontrol:

  • Sistem bisa runtuh karena terlalu agresif mencoba ulang

Retry pattern adalah kompromi antara ketahanan dan stabilitas.


Retry Langsung (Immediate Requeue) #

Pendekatan paling sederhana:

Consumer melakukan:

basic.nack(requeue = true)

Message langsung kembali ke queue utama.

Kelebihan #

  • Implementasi sangat sederhana
  • Tidak perlu queue tambahan

Kekurangan #

  • Tidak ada delay
  • Berisiko infinite loop
  • Tidak membedakan transient vs permanent error
  • Tidak cocok untuk production

Immediate requeue jarang direkomendasikan untuk sistem serius.


Retry dengan TTL + Dead Letter Exchange (Dasar) #

Pendekatan yang lebih sehat menggunakan:

  • Dead Letter Exchange (DLX)
  • Retry queue
  • TTL

1. Diagram Retry Dasar #

Main Queue
   |
   | gagal (nack requeue=false)
   v
Retry Queue (TTL 10 detik)
   |
   v
Main Exchange

Alur:

  1. Message gagal
  2. Nack dengan requeue=false
  3. Masuk ke retry queue
  4. TTL habis
  5. Message kembali ke exchange utama
  6. Diproses ulang

Pendekatan ini memberi delay sebelum retry.


Retry dengan Exponential Backoff #

Alih-alih delay tetap, kita bisa meningkatkan delay setiap percobaan.

Contoh pola:

  • Retry 1 → 1 detik
  • Retry 2 → 2 detik
  • Retry 3 → 4 detik
  • Retry 4 → 8 detik

Implementasi dapat dilakukan dengan:

1️⃣ Multiple Retry Queue Berjenjang #

Retry-1 (TTL 1s)
Retry-2 (TTL 2s)
Retry-3 (TTL 4s)
Retry-4 (TTL 8s)

Setiap kegagalan dipindahkan ke queue berikutnya.

2️⃣ Single Retry Queue + Dynamic TTL #

  • Simpan x-retry-count di header
  • Hitung delay di aplikasi
  • Publish ulang dengan TTL baru

Pendekatan kedua lebih fleksibel dan scalable.


Retry Counter: Komponen Wajib #

Setiap retry pattern harus memiliki batas.

Tambahkan header:

  • x-retry-count

Alur umum:

  1. Message gagal
  2. Tambah retry-count
  3. Jika retry-count < max → kirim ke retry queue
  4. Jika retry-count ≥ max → kirim ke DLQ permanen

Tanpa retry counter, retry bisa tak terbatas.


Retry dengan Delayed Exchange Plugin #

RabbitMQ memiliki plugin bernama:

rabbitmq_delayed_message_exchange

Dengan plugin ini:

  • Kita bisa menentukan delay langsung saat publish
  • Tidak perlu queue TTL terpisah

Contoh konsep:

x-delay = 5000

Plugin ini menyederhanakan arsitektur retry.

Namun:

  • Tidak selalu tersedia di semua environment
  • Perlu instalasi tambahan

Perbandingan Retry Pattern #

PatternKompleksitasStabilitasCocok untuk
Immediate RequeueRendahRendahDemo / test
TTL + DLX (Fixed Delay)SedangBaikTransient ringan
Exponential BackoffTinggiSangat baikDependency outage
Delayed Exchange PluginSedangBaikArsitektur modern

Untuk production-grade system, exponential backoff + retry limit adalah standar.


Retry dan Ordering #

Retry dapat memengaruhi ordering.

Message yang gagal akan diproses lebih lambat dibanding message berikutnya.

Jika ordering sangat penting:

  • Gunakan partitioned queue berdasarkan key
  • Atau desain consumer agar idempotent dan tolerant terhadap out-of-order

Retry dan strict ordering jarang bisa dipertahankan bersamaan.


Retry dan Quorum Queue #

Pada quorum queue:

  • Retry tetap menggunakan DLX + TTL
  • Replikasi tetap konsisten
  • Duplicate tetap mungkin terjadi

Retry logic tetap berada di level aplikasi.


Kesalahan Umum dalam Retry Pattern #

  • Tidak membedakan error transient dan permanen
  • Retry tanpa batas
  • Tidak memiliki DLQ final
  • Tidak memonitor retry rate
  • Tidak menggunakan jitter pada backoff

Retry yang buruk lebih berbahaya daripada tidak retry sama sekali.


Best Practice Production #

  • Gunakan exponential backoff
  • Tambahkan jitter kecil untuk menghindari thundering herd
  • Batasi retry count
  • Pisahkan retry queue dan DLQ permanen
  • Monitor retry rate dan DLQ depth
  • Dokumentasikan retry policy sebagai bagian kontrak sistem

Retry adalah bagian dari reliability architecture, bukan sekadar fitur tambahan.


Ringkasan #

KomponenPeran
Retry queueMenunda percobaan ulang
TTLMengatur delay
DLXMengalihkan pesan gagal
Retry counterMembatasi percobaan
BackoffMengurangi retry storm

Penutup #

Retry pattern adalah salah satu fondasi penting dalam sistem messaging modern.

Ia menentukan apakah sistem akan:

  • Pulih dengan elegan
  • Atau menghancurkan dirinya sendiri karena terlalu agresif mencoba lagi

Dalam RabbitMQ, retry bukan fitur bawaan yang otomatis aman.

Ia harus dirancang secara sadar dengan mempertimbangkan:

  • Stabilitas dependency
  • Ordering
  • Duplicate handling
  • Observability

Karena dalam sistem asynchronous, ketahanan bukan hanya soal bisa mencoba lagi.

Tetapi soal tahu kapan harus mencoba, seberapa lama menunggu, dan kapan harus berhenti.

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