flutter_resilience
A production-ready Flutter/Dart package for network resilience, providing automatic API retry, exponential backoff, and circuit breaker functionality.
Overview
In modern mobile applications, network requests are prone to transient failures. flutter_resilience helps you build robust applications by providing a suite of resilience policies inspired by Polly, but designed specifically for the Flutter and Dart ecosystem.
Key Features
- 🔄 Automatic Retry: Effortlessly retry failed operations.
- 📈 Exponential Backoff & Jitter: Avoid overwhelming your backend with smart delay strategies.
- ⚡ Circuit Breaker: Prevent cascading failures by failing fast when a service is down.
- ⏱️ Timeout Handling: Ensure your app stays responsive by enforcing execution limits.
- 🛡️ Fallback Logic: Provide graceful degradation with secondary data sources.
- 🔗 Policy Composition: Combine multiple strategies into a single execution pipeline.
Why Quality Retry Logic Matters
Most developers implement basic for loops for retries, which often lack:
- Wait and Retry: Retrying immediately can exacerbate server load.
- Jitter: Simultaneous retries from many clients can create a "thundering herd" effect.
- Circuit Breaking: Continuing to hit a dead service wastes battery and data.
flutter_resilience handles these complexities for you.
Installation
Add this to your pubspec.yaml:
dependencies:
flutter_resilience: ^1.0.1
Quick Start
Simple Retry
final client = ResilientClient(retries: 3);
final response = await client.execute(() {
return http.get(Uri.parse("https://api.example.com/data"));
});
Exponential Backoff with Jitter
final client = ResilientClient(
retries: 5,
strategy: RetryStrategy.jitter,
retryDelay: Duration(seconds: 1),
);
Circuit Breaker
final circuitBreaker = CircuitBreaker(
failureThreshold: 5,
resetTimeout: Duration(seconds: 30),
);
final client = ResilientClient(circuitBreaker: circuitBreaker);
Fallback Support
final data = await client.execute(
() => api.fetchData(),
fallback: () => myOfflineCache.getData(),
);
Advanced Composition
You can compose policies manually for more control:
final policy = ResiliencePolicy(
retry: RetryPolicy(maxRetries: 3),
timeout: TimeoutPolicy(timeout: Duration(seconds: 2)),
circuitBreaker: CircuitBreaker(failureThreshold: 3),
);
final result = await policy.execute(() => myAsyncAction());
Performance
- Zero unnecessary allocations: Designed for high-frequency requests.
- Thread-safe: Safe to use across multiple isolates if needed.
- Minimal overhead: Adds less than 1ms to the execution pipeline (excluding delays).
Comparison
| Feature | flutter_resilience |
Manual Retry |
|---|---|---|
| Exponential Backoff | ✅ | ❌ (Hard) |
| Jitter Support | ✅ | ❌ |
| Circuit Breaker | ✅ | ❌ |
| Fallback Logic | ✅ | ⚠️ (Manual) |
| Pipeline Composition | ✅ | ❌ |
Best Practices
- Use Jitter: Always use jitter for public-facing APIs to spread out retry load.
- Filter Exceptions: Only retry on transient errors (e.g.,
SocketException,TimeoutException) using theretryIfparameter. - Dispose: Call
dispose()onCircuitBreakerif it has a long-running timer and is no longer needed.
License
MIT License - see LICENSE for details.