
- Resilience: the system’s ability to recover from failures—restarting processes, requeuing work, degrading gracefully, or automatically reconciling state.
- Fault tolerance: the system’s ability to continue operating correctly even when parts fail—through redundancy, graceful degradation, and isolation.
- Services lock up or become unresponsive (stuck threads, deadlocks).
- Downstream components become unavailable (network partitions, crashed services).
- Data corruption or race conditions under concurrent load.
- Cascading failures when one overloaded service causes others to fail.
Resilience and fault tolerance are complementary: resilience focuses on recovery and adaptation after failures; fault tolerance focuses on continuing correct operation despite failures. Designing both into your system reduces downtime and limits user impact when things go wrong.
Practical guidance
- Combine patterns: use timeouts + retries + circuit breakers for robust remote calls.
- Make retries safe: design APIs and operations to be idempotent or use deduplication keys.
- Use bulkheads to prevent a failing dependency from exhausting shared resources (threads, connections).
- Add observability: metrics, distributed tracing, and structured logs are essential for diagnosing intermittent issues.
- Test with chaos experiments (chaos engineering) and load testing to reveal behavior under failure scenarios.
- Design for graceful degradation: return reduced functionality rather than complete failure when components degrade.
Be careful with naive retries: aggressive retries can amplify load and cause cascading failures. Always use backoff, jitter, and circuit breakers—and ensure operations are idempotent when possible.
- Timeouts: always for external IO (HTTP, DB, RPC).
- Retries: for transient network or service errors, not for persistent failures.
- Circuit breakers: when a downstream service has intermittent high latency or error spikes.
- Bulkheads: in multi-tenant systems or when a single dependency can monopolize resources.
- Rate limiting: at service boundaries (API gateways) and for abusive clients.
- Kubernetes Documentation — reliability patterns for distributed systems.
- Circuit Breaker pattern (Martin Fowler) — conceptual guide.
- Designing Data-Intensive Applications — patterns for resilience and fault tolerance.
- Resilience4j — modern Java library implementing circuit breakers, bulkheads, retries.