Skip to main content
Marco Rossi·

Wrapped our flaky payment client in a real circuit breaker and the 3am pages stopped

Implements comprehensive error handling, retry logic, circuit breakers, and graceful degradation for any codebase.

Error Handling & Resilience Patterns

You are a reliability engineer implementing production-grade error handling. Harden the following code with comprehensive resilience patterns. ## Current Code ```{{programming_language}} {{current_code}} ``` ## Resilience Requirements - Language: {{programming_language}} - Framework: {{framework}} - Error strategy: {{error_strategy}} (fail-fast, graceful-degradation, retry) ## Patterns to Implement 1. **Structured Error Hierarchy** - Domain-specific error classes extending a base error 2. **Centralized Error Handler** - Catch-all middleware/handler formatting errors consistently 3. **Retry Logic** - Exponential backoff with jitter for transient failures 4. **Circuit Breaker** - Open/half-open/closed states for external service calls 5. **Timeout Handling** - Per-operation timeouts preventing hanging requests 6. **Bulkhead Pattern** - Resource isolation preventing cascade failures 7. **Graceful Degradation** - Fallback responses when dependencies fail 8. **Error Logging** - Structured logging with correlation IDs, no PII 9. **User-Facing Errors** - Sanitized error messages for API responses 10. **Alerting Hooks** - Integration points for PagerDuty/OpsGenie on critical errors ## Output 1. Complete refactored code with all patterns integrated 2. Error class hierarchy diagram (ASCII) 3. Sequence diagram showing retry and circuit breaker flow 4. Configuration options for tuning timeouts and retry counts 5. Unit tests verifying error handling paths

Ergebnisse

Hardened the `PaymentClient.charge()` call in this Express + TypeScript service with a graceful-degradation strategy. ## Error hierarchy ``` AppError ├── TransientError (retryable: timeout, 503) ├── PaymentDeclined (terminal, user-facing) └── DependencyDownError (circuit open → degrade) ``` ```typescript const breaker = new CircuitBreaker({ threshold: 5, resetMs: 30_000 }); export async function charge(intent: Intent): Promise<Receipt> { return retry( () => breaker.run(() => withTimeout(gateway.charge(intent), 4_000), // per-op timeout ), { retries: 3, backoff: (n) => 2 ** n * 200 + Math.random() * 100, // jitter retryOn: (e) => e instanceof TransientError, }, ); } ``` ## Retry + breaker flow ``` charge ─▶ retry ─▶ breaker(closed) ─▶ timeout(4s) ─▶ gateway ▲ │ TransientError │ └─backoff─┘ fail×5 ─▶ breaker OPEN ─▶ DependencyDownError ─▶ queue for later ``` **User-facing:** declines surface as `"Card declined"`; everything else returns a sanitized `"Payment temporarily unavailable"` with a correlation id logged for PagerDuty. Timeouts and retry counts are config-driven via `PAYMENT_TIMEOUT_MS` / `PAYMENT_MAX_RETRIES`.

Modell: Claude Sonnet 4

9 Likes4 SavesScore: 5

1 Kommentar

Daniel Cohen·

Great structure, though I'd add a retry cap. Still, super useful.