tower-resilience
A comprehensive resilience and fault-tolerance toolkit for Tower services, inspired by Resilience4j.
About
Tower-resilience provides composable middleware for building robust distributed systems in Rust. Tower is a library of modular and reusable components for building robust networking clients and servers. This crate extends Tower with resilience patterns commonly needed in production systems.
Inspired by Resilience4j, a fault tolerance library for Java, tower-resilience adapts these battle-tested patterns to Rust's async ecosystem and Tower's middleware model.
Resilience Patterns
- Circuit Breaker - Prevents cascading failures by stopping calls to failing services
- Bulkhead - Isolates resources to prevent system-wide failures
- Time Limiter - Advanced timeout handling with cancellation support
- Retry - Intelligent retry with exponential backoff and jitter
- Rate Limiter - Controls request rate to protect services
- Cache - Response memoization to reduce load
Features
- Composable - Stack multiple resilience patterns using Tower's ServiceBuilder
- Observable - Event system for monitoring pattern behavior (retries, state changes, etc.)
- Configurable - Builder APIs with sensible defaults
- Async-first - Built on tokio for async Rust applications
- Zero-cost abstractions - Minimal overhead when patterns aren't triggered
Quick Start
[]
= "0.1"
= "0.5"
use ServiceBuilder;
use *;
let service = new
.layer
.layer
.service;
Examples
Circuit Breaker
Prevent cascading failures by opening the circuit when error rate exceeds threshold:
use CircuitBreakerLayer;
let layer = builder
.failure_rate_threshold // Open at 50% failure rate
.sliding_window_size // Track last 100 calls
.build;
See examples/circuitbreaker.rs for a complete example.
Bulkhead
Limit concurrent requests to prevent resource exhaustion:
use BulkheadLayer;
let layer = builder
.max_concurrent_calls
.wait_timeout
.build;
See examples/bulkhead.rs for a complete example.
Time Limiter
Enforce timeouts on operations:
use TimeLimiterConfig;
let config = builder
.timeout_duration
.cancel_running_future
.build;
Retry
Retry failed requests with exponential backoff:
use ;
let config: = builder
.max_attempts
.exponential_backoff
.build;
Rate Limiter
Control request rate to protect downstream services:
use RateLimiterConfig;
let config = builder
.max_permits
.refresh_period
.build;
Cache
Cache responses to reduce load on expensive operations:
use CacheConfig;
let config = builder
.max_capacity
.ttl
.key_extractor
.build;
Pattern Composition
Stack multiple patterns for comprehensive resilience:
use ServiceBuilder;
// Client-side: timeout -> circuit breaker -> retry
let client = new
.layer
.layer
.layer
.service;
// Server-side: rate limit -> bulkhead -> timeout
let server = new
.layer
.layer
.layer
.service;
Performance
Benchmarks measure the overhead of each pattern in the happy path (no failures, circuit closed, permits available):
| Pattern | Overhead (ns) | vs Baseline |
|---|---|---|
| Baseline (no middleware) | ~10 ns | 1.0x |
| Retry (no retries) | ~80-100 ns | ~8-10x |
| Time Limiter | ~107 ns | ~10x |
| Rate Limiter | ~124 ns | ~12x |
| Bulkhead | ~162 ns | ~16x |
| Cache (hit) | ~250 ns | ~25x |
| Circuit Breaker (closed) | ~298 ns | ~29x |
| Circuit Breaker + Bulkhead | ~413 ns | ~40x |
Key Takeaways:
- All patterns add < 300ns overhead individually
- Overhead is additive when composing patterns
- Even the heaviest pattern (circuit breaker) is negligible for most use cases
- Retry and time limiter are the lightest weight options
Run benchmarks yourself:
Documentation
- API Documentation
- Pattern Guides - In-depth guides on when and how to use each pattern
Examples
Two sets of examples are provided:
- Top-level examples - Simple, getting-started examples matching this README (one per pattern)
- Module examples - Detailed examples in each crate's
examples/directory showing advanced features
Run top-level examples with:
# etc.
Why tower-resilience?
Tower provides some built-in resilience (timeout, retry, rate limiting), but tower-resilience offers:
- Circuit Breaker - Not available in Tower
- Advanced retry - More backoff strategies and better control
- Bulkhead - True resource isolation with async-aware semaphores
- Unified events - Consistent observability across all patterns
- Builder APIs - Ergonomic configuration with sensible defaults
- Production-ready - Patterns inspired by battle-tested Resilience4j
Minimum Supported Rust Version (MSRV)
This crate's MSRV is 1.64.0, matching Tower's MSRV policy.
We follow Tower's approach:
- MSRV bumps are not considered breaking changes
- When increasing MSRV, the new version must have been released at least 6 months ago
- MSRV is tested in CI to prevent unintentional increases
License
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Contributing
Contributions are welcome! Please see the contributing guidelines for more information.