flutter_resilience

A production-ready Flutter/Dart package for network resilience, providing automatic API retry, exponential backoff, and circuit breaker functionality.

pub package likes license

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:

  1. Wait and Retry: Retrying immediately can exacerbate server load.
  2. Jitter: Simultaneous retries from many clients can create a "thundering herd" effect.
  3. 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

  1. Use Jitter: Always use jitter for public-facing APIs to spread out retry load.
  2. Filter Exceptions: Only retry on transient errors (e.g., SocketException, TimeoutException) using the retryIf parameter.
  3. Dispose: Call dispose() on CircuitBreaker if it has a long-running timer and is no longer needed.

License

MIT License - see LICENSE for details.

Libraries

flutter_resilience