Circuit Breaker Pattern: Membangun Sistem Resilient
Daftar Isi
- Pendahuluan
- Masalah yang Diselesaikan Circuit Breaker
- Cara Kerja Circuit Breaker
- Closed, Open, dan Half-Open State
- Contoh: Recommendation Service yang Sedang Bermasalah
- Circuit Breaker vs Retry
- Strategi Fallback
- Apa yang Perlu Dimonitor?
- Kesalahan Umum
- Checklist
- FAQ
- Kesimpulan
Pendahuluan
Distributed system bisa gagal dengan cara yang berantakan. Payment provider melambat. Recommendation service error. Database replica tidak tersedia. Jika semua caller terus retry agresif, satu failure bisa menyebar ke seluruh sistem.
Circuit breaker pattern membantu menghentikan penyebaran itu.
Pattern ini memantau call ke dependency. Saat failure melewati threshold, circuit breaker sementara berhenti mengirim traffic ke dependency tersebut dan mengembalikan fallback atau fast failure.
Masalah yang Diselesaikan Circuit Breaker
Tanpa circuit breaker, caller bisa membanjiri service yang sedang bermasalah.
| Situasi | Tanpa circuit breaker |
|---|---|
| dependency lambat | thread dan koneksi menumpuk |
| dependency error | caller terus retry |
| provider outage | request user menunggu sampai timeout |
| partial failure | failure menyebar ke service lain |
Tujuannya bukan menyembunyikan failure. Tujuannya adalah fail fast, melindungi resource, dan memberi dependency waktu untuk pulih.
Cara Kerja Circuit Breaker
Circuit breaker melacak hasil call terbaru.
Sinyal yang umum:
- failure rate
- timeout rate
- slow call rate
- jumlah concurrent request
Saat failure threshold tercapai, breaker masuk state open. Call berhenti dikirim ke dependency yang tidak sehat selama beberapa waktu.
Closed, Open, dan Half-Open State
Circuit breaker biasanya punya tiga state.
| State | Artinya |
|---|---|
| Closed | call berjalan normal |
| Open | call fail fast atau memakai fallback |
| Half-open | sebagian kecil test call diizinkan |
Contoh alur:
Closed -> failure naik -> Open -> tunggu -> Half-open -> sukses -> Closed
Jika test call di half-open gagal, breaker kembali open.
Contoh: Recommendation Service yang Sedang Bermasalah
Bayangkan halaman product detail memanggil recommendation-service untuk menampilkan produk terkait. Fitur ini berguna, tapi bukan bagian kritikal dari checkout. Kalau service rekomendasi sedang lambat, halaman utama produk sebaiknya tetap tampil.
Tanpa circuit breaker, setiap request user tetap menunggu call rekomendasi sampai timeout. Jika traffic sedang tinggi, thread, koneksi, dan worker bisa ikut penuh hanya karena fitur tambahan sedang bermasalah.
Dengan circuit breaker, flow-nya bisa dibuat seperti ini:
| Kondisi | Perilaku aplikasi |
|---|---|
| service sehat | tampilkan rekomendasi dari API |
| beberapa call gagal | catat failure dan lanjut pantau |
| failure melewati threshold | breaker open, call ke API dihentikan sementara |
| breaker open | tampilkan fallback, misalnya produk populer dari cache |
| setelah cooldown | izinkan beberapa test call di half-open |
| test call sukses | breaker closed, traffic normal lagi |
| test call gagal | breaker open lagi |
Contoh implementasi sederhana:
type BreakerState = "closed" | "open" | "half-open";
class SimpleCircuitBreaker {
private state: BreakerState = "closed";
private failures = 0;
private openedAt = 0;
constructor(
private readonly failureThreshold = 3,
private readonly cooldownMs = 10_000,
) {}
async run<T>(operation: () => Promise<T>, fallback: () => T): Promise<T> {
if (this.state === "open") {
const readyForTest = Date.now() - this.openedAt > this.cooldownMs;
if (!readyForTest) {
return fallback();
}
this.state = "half-open";
}
try {
const result = await operation();
this.failures = 0;
this.state = "closed";
return result;
} catch (error) {
this.failures += 1;
if (this.state === "half-open" || this.failures >= this.failureThreshold) {
this.state = "open";
this.openedAt = Date.now();
}
return fallback();
}
}
}
Pemakaiannya:
const recommendationBreaker = new SimpleCircuitBreaker(3, 10_000);
async function getProductRecommendations(productId: string) {
return recommendationBreaker.run(
() => fetchRecommendationsFromApi(productId),
() => getPopularProductsFromCache(),
);
}
Di production, kamu biasanya tidak menulis circuit breaker sendiri. Banyak stack sudah punya library resilience yang lebih matang, misalnya dengan metrics, sliding window, concurrency limit, dan event hook. Namun contoh kecil ini menunjukkan inti polanya: saat dependency tidak sehat, aplikasi berhenti memaksanya bekerja dan memilih respons yang lebih aman.
Circuit Breaker vs Retry
Retry dan circuit breaker menyelesaikan bagian resilience yang berbeda.
| Pattern | Membantu saat | Risiko |
|---|---|---|
| Retry | failure sementara | bisa memperbesar load |
| Timeout | dependency terlalu lambat | bisa memotong pekerjaan lambat tapi valid |
| Circuit breaker | dependency tidak sehat | bisa menolak call saat recovery |
Gunakan bersama dengan hati-hati. Retry perlu limit, backoff, dan jitter. Circuit breaker mencegah retry berubah menjadi badai traffic.
Strategi Fallback
Fallback harus berguna dan jujur.
Contoh:
- mengembalikan cached data
- menampilkan pengalaman yang degraded
- memasukkan pekerjaan ke queue
- melewati recommendation yang tidak kritikal
- mengembalikan error jelas untuk aksi kritikal
Tidak semua operasi butuh fallback. Untuk payment capture, fake success berbahaya. Untuk product recommendation, menyembunyikan widget mungkin aman.
Apa yang Perlu Dimonitor?
Circuit breaker butuh observability.
Pantau:
- perubahan state breaker
- latency dependency
- jumlah timeout
- jumlah fallback
- jumlah rejected call
- recovery success rate
- user-facing error rate
Contoh dashboard:
| Metric | Sinyal sehat |
|---|---|
| open breaker count | rendah dan tidak lama |
| fallback rate | sesekali, bukan terus-menerus |
| dependency latency | dalam batas SLO |
| half-open success | naik saat recovery |
Kesalahan Umum
Terlalu banyak retry sebelum breaker open
Retry berlebihan bisa membuat dependency makin parah. Jaga retry budget tetap kecil.
Memakai threshold yang sama untuk semua dependency
Dependency kritikal, dependency opsional, dan integrasi batch yang lambat butuh setting berbeda.
Fallback yang menyesatkan
Fallback tidak boleh berpura-pura aksi berhasil jika sebenarnya tidak.
State breaker tidak terlihat
Jika tim tidak bisa melihat kapan breaker open, debugging berubah jadi tebak-tebakan.
Checklist
- Set timeout sebelum menambah retry.
- Gunakan retry terbatas dengan backoff dan jitter.
- Definisikan failure threshold per dependency.
- Pilih fallback yang jujur.
- Track perubahan state breaker.
- Alert jika breaker open terlalu lama.
- Test recovery half-open.
- Hindari fake success untuk write kritikal.
- Dokumentasikan pengalaman user saat fallback.
FAQ
Apakah circuit breaker hanya untuk microservices?
Tidak. Pattern ini berguna untuk dependency yang tidak selalu stabil: external API, database, queue, search service, dan internal service.
Apakah semua dependency perlu circuit breaker?
Tidak selalu. Gunakan saat failure bisa menghabiskan resource, memicu cascading failure, atau merusak pengalaman user.
Apakah circuit breaker menggantikan monitoring?
Tidak. Circuit breaker mengurangi blast radius, tapi kamu tetap butuh monitoring untuk memahami dan memperbaiki sumber masalahnya.
Kesimpulan
Circuit breaker membuat sistem lebih resilient dengan menghentikan dependency yang tidak sehat agar tidak menghabiskan resource tanpa batas.
Pattern ini paling efektif jika digabung dengan timeout, retry terbatas, fallback yang jujur, dan observability yang kuat. Polanya sederhana, tapi perilaku production-nya bergantung pada threshold dan dampak user yang dipikirkan dengan matang.
Artikel Terkait
Lanjutkan membaca topik yang masih satu konteks.
Saga Pattern: Mengelola Distributed Transactions
Pelajari saga pattern untuk distributed transaction, termasuk choreography, orchestration, compensating action, failure handling, dan trade-off praktis.
Event Sourcing: Membangun Sistem yang Dapat Diaudit
Pahami event sourcing lewat contoh praktis, event stream, projection, audit trail, trade-off, dan kapan pattern ini layak dipakai.
Hexagonal Architecture: Memahami Ports dan Adapters
Pahami hexagonal architecture lewat ports, adapters, arah dependency, manfaat testing, contoh use case, trade-off, dan panduan implementasi praktis.
Contract Testing: Jaga API Microservice Tetap Kompatibel
Gunakan contract testing untuk menjaga API microservice tetap kompatibel, mengurangi bug integrasi, memperkuat CI, dan membuat deployment lebih aman.