Ana Sayfa / Blog / Circuit breaker pattern’ini production’da gördüğüm yerler

Circuit breaker pattern’ini production’da gördüğüm yerler

Downstream service çökünce sen de çökme. Circuit breaker pattern ne zaman gerekli, nasıl doğru implement edilir?

Kullanıcı login olmaya çalışıyor, auth server 5 saniye timeout veriyor. 1000 kullanıcı aynı anda deniyor, server’ın tüm connection pool’u bu bekleyen istekler için çalışıyor. Ana server bile çöküyor. Cascade failure.

Bu senaryoyu önleyen pattern: Circuit breaker. Downstream servis hasta ise, ona request göndermeyi durdur. Kullanıcıya hızlı fail dön. Server’ı koruyacak.

12 SaaS projesinde circuit breaker implementation’ı gördüm. Yapılan 4 farklı hata ve doğru implementation’ı anlatacağım.

Circuit breaker states

Classic pattern 3 state’li:

Closed: Normal durum. Her request downstream’e gidiyor. Failure count takip ediliyor.

Open: Threshold aşıldı (X failure / Y time window). Request’ler downstream’e gitmiyor. Kullanıcıya hemen fail response. Server’ı koruyoruz.

Half-Open: Belirli süre sonra (30sec, 1min) trial request izin veriliyor. Success ise Closed’a dön. Failure ise Open’a geri.

Closed → (X failures) → Open → (timeout) → Half-Open → (success) → Closed
                                                      → (failure) → Open

Bu basit state machine downstream service’i protect ediyor.

Gerçek implementation örneği

En popüler library Netflix Hystrix (deprecated ama pattern’i örnek). Modern alternative: resilience4j (Java), Polly (.NET), opossum (Node.js), Go’da go-resilience.

Node.js example (opossum):

const CircuitBreaker = require('opossum');

const options = {
  timeout: 3000, // 3 saniyede cevap gelmezse timeout
  errorThresholdPercentage: 50, // %50 failure'da open et
  resetTimeout: 30000 // 30 saniye bekle Half-Open'a geç
};

const breaker = new CircuitBreaker(callAuthService, options);

breaker.fallback(() => {
  return { authenticated: false, reason: 'Auth service unavailable' };
});

breaker.on('open', () => console.log('Auth service circuit is OPEN'));
breaker.on('halfOpen', () => console.log('Circuit trying recovery'));

// Use
try {
  const result = await breaker.fire(userId, password);
} catch (error) {
  // Hem downstream error hem circuit open için
}

breaker.fire() eğer circuit Closed ise callAuthService‘i çağırıyor. Open ise fallback dönüyor hızlıca.

Yapılan 4 yanlış

Yanlış 1: Every downstream call’a circuit breaker

Her external call’ı circuit breaker ile sarmak overkill. Circuit breaker state yönetimi overhead ekliyor.

Doğru: kritik downstream service’lere uygula. Non-critical calls (logging, analytics) direct fail, fallback ile.

Yanlış 2: Threshold çok düşük

ErrorThresholdPercentage %10 ise geçici network glitch’leri bile circuit’i açıyor. Legitimate failure’ları hızlı tespit etmek için %40-60 arası makul.

Yanlış 3: Reset timeout sabit

30 saniye reset timeout default olabilir ama farklı servis’ler farklı recovery süreleri gerektirebiliyor. Payment API’nin recovery’si email service’inden daha yavaş.

Adaptive timeout kullanabilirsin: downstream response time’a göre dynamic.

Yanlış 4: Fallback logic yok

Circuit open olunca ne olacak? Fallback gerek. Options:

  • Cached response (stale data)
  • Default value (guest experience)
  • Degraded feature (basic search yerine advanced search)
  • Graceful error message

Fallback olmadan circuit breaker sadece hata mesajını hızlandırıyor, kullanıcı deneyimini iyileştirmiyor.

Ne zaman kullanılmalı?

Circuit breaker shine yaptığı scenario’lar:

1. Network call’ları to external services. Third-party API (Stripe, Sendgrid, geocoder). Provider down’sa sen çökme.

2. Database calls (rare ama mümkün). Database down’sa graceful degradation.

3. Cache servers. Redis down’sa application direct DB’ye gitmesin, cache bypass ile çalışsın.

4. Internal microservice calls. Service A, service B’ye bağımlı. B yavaşsa A da yavaşlamasın.

Ne zaman kullanmayın

1. Synchronous mission-critical operations. Ödeme işlemi. Circuit açık olsa bile user ödemek istiyor. Alternative payment path lazım, circuit breaker yetmiyor.

2. Transient network issue’ları. Retries daha uygun. Circuit breaker persistent failure’lar için.

3. Rate-limited by design operations. Rate limit hit ediyorsan, circuit breaker rate limit provider ile karışıyor. Exponential backoff daha uygun.

Circuit breaker + retry combination

Typically ikisi birlikte kullanılır:

  1. Retry: Transient failure için 2-3 kez tekrar dene, exponential backoff ile.
  2. Circuit breaker: Persistent failure için, retry’lardan sonra.

Order önemli: önce retry, sonra circuit breaker. Çünkü retry temporary issue’ları handle ediyor, circuit breaker persistent.

async function callWithResilience() {
  return await circuitBreaker.fire(async () => {
    return await retryWithBackoff(async () => {
      return await downstream.call();
    }, { maxAttempts: 3 });
  });
}

Monitoring circuit breaker

Circuit breaker state’lerini monitor etmek kritik:

Metrics:
– Current state (Closed/Open/Half-Open)
– Time in each state
– Failure rate
– Request count per state

Alerts:
– Circuit Open olduğunda PagerDuty
– Open state > 5 dakika → Slack notification
– Multiple circuit’ler aynı anda Open → Major incident

Dashboards:
– Per-service circuit breaker state
– Historical state transitions
– Failure rate trends

Bu visibility olmadan circuit breaker silently çalışıyor, team fark etmiyor sistem degraded.

Bulkhead pattern (tamamlayıcı)

Circuit breaker’ın kuzeni: bulkhead pattern. Connection pool’ları separate et ki bir service call’ı diğerlerini bloke etmesin.

Scenario: Service A auth, database, payment calling. Auth slow, connection pool’u doldurdu. Database ve payment call’ları da bloke.

Bulkhead fix: Her downstream için dedicated thread pool veya connection pool. Auth yavaşsa sadece auth’un pool’u tükeniyor, database ve payment etkilenmiyor.

Circuit breaker + bulkhead = comprehensive resilience.

Service mesh integration

Kubernetes microservice sistemlerde Istio, Linkerd gibi service mesh’ler circuit breaker built-in veriyor. Her pod bir sidecar proxy’e sahip, proxy circuit breaker implement ediyor.

Advantage: application code değişmez. Infrastructure katmanında handle ediliyor.

Disadvantage: customization limited. Language-specific business logic’i sidecar’da yazmak zor.

Hybrid: service mesh basic circuit breaking, application-level fine-tuned breakers önemli service’ler için.

Real story: Stripe API integration

Bir e-ticaret projesinde Stripe API çağrılarını circuit breaker ile sardım. Stripe 2 saatlik bir outage yaşadı (rare ama oluyor).

Circuit breaker olmadan ne olurdu:
– Her ödeme denemesi 30 saniye hanging
– Tüm connection pool Stripe bekler halde
– Ana application çökmeye başlar
– Support tickets patlar

Circuit breaker ile:
– Stripe 30 saniye timeout veriyor, circuit 2 dakika içinde Open
– Payment attempts hemen fail, kullanıcıya “Ödeme geçici sorun, birkaç dakika sonra tekrar deneyin” mesajı
– Application rest of functionality sürüyor (catalog browsing, account management)
– Stripe düzelince circuit Half-Open → Closed

2 saatlik Stripe outage süresince sistem degraded ama ayakta. Customer impact contained.

Testing circuit breakers

Chaos engineering approach:

Unit test: Circuit breaker library’nin state transition’larını test et. Mock downstream errors, state kontrolleri.

Integration test: Actual downstream simulated slow/fail response. Circuit gerçekten açılıyor mu?

Production testing: Controlled downstream failure injection. Chaos monkey-style. Weekend’de test environment’ta.

Game days: Quarterly. Simulate full service failure. Team’in response prosedürü test edilsin.

Configuration tuning

Default config rarely optimal. Tune per service:

Fast downstream (response <100ms):
– Timeout: 1 second
– Failure threshold: %30
– Reset: 10 seconds

Medium downstream (response 100-500ms):
– Timeout: 3 seconds
– Failure threshold: %50
– Reset: 30 seconds

Slow downstream (response 1-5sec):
– Timeout: 10 seconds
– Failure threshold: %60
– Reset: 60 seconds

Bu değerleri actual traffic pattern’ı ile ayarla. Prometheus metrics’e bak.

Sonuç

Circuit breaker pattern microservice reliability’nin temel aracı. Cascade failure prevention için kritik.

Every call’a uygulamayın, kritik downstream’lere odaklan. Retry + circuit breaker kombine kullan. Fallback logic önemli. Monitoring ve alerting mandatory.

Implementation: opossum, resilience4j, Polly – proven library’ler var. Custom yazmaya gerek yok. Configuration’ı tune et, yanlış default’lar çok yaygın.

Bir production incident’ın maliyetini hesapladığında, circuit breaker 2-3 saatlik implementation yatırımını kat kat geri ödüyor.

Bu konuda bir projeniz mi var?

Kısa bir özet bırakın, 24 saat içinde size dönüş yapayım.

İletişime Geç