Robust Provider
Robust, retrying wrapper around Alloy providers.
Currently production-ready for supported features. The API surface is still evolving and future feature additions may introduce breaking changes and/or changes in assumptions.
About
Robust Provider is a Rust library that wraps Alloy providers with production-ready resilience features. It adds automatic retries, timeouts, and transparent failover between multiple RPC endpoints - making it ideal for applications that need reliable blockchain connectivity.
Table of Contents
Features
- Bounded timeouts - per-call timeouts prevent indefinite hangs on unresponsive RPC endpoints.
- Exponential backoff retries - automatic retry with configurable backoff for transient failures.
- Transparent failover - seamlessly switch from a primary provider to one or more fallback providers.
- Resilient subscriptions - WebSocket block subscriptions with automatic reconnection and lag detection.
Quick Start
Add robust-provider to your Cargo.toml:
[]
= "1.0.1"
Create a robust provider with automatic retries and fallback:
use ;
use RobustProviderBuilder;
use Duration;
use StreamExt;
async
Usage
Building a Provider
RobustProviderBuilder provides a fluent API for constructing a RobustProvider with custom settings:
use ProviderBuilder;
use RobustProviderBuilder;
use Duration;
// Standard configuration with retries
let provider = new.connect.await?;
let robust = new
.call_timeout
.max_retries
.build
.await?;
// With multiple fallback providers
let primary = new.connect.await?;
let fallback_1 = new.connect.await?;
let fallback_2 = new.connect_http;
let robust = new
.fallback
.fallback
.build
.await?;
Configuration Options
| Option | Default | Description |
|---|---|---|
call_timeout |
60s | Maximum time for RPC operations before timing out |
subscription_timeout |
120s | Maximum time to wait for subscription messages |
max_retries |
3 | Number of retry attempts before failing over |
min_delay |
1s | Base delay for exponential backoff between retries |
reconnect_interval |
30s | Interval between primary provider reconnection attempts (for subscription) |
subscription_buffer_capacity |
128 | Buffer size for subscription streams |
Subscriptions
RobustSubscription wraps Alloy's block subscriptions with automatic failover and reconnection:
let robust = new
.fallback
.subscription_timeout
.reconnect_interval
.build
.await?;
let subscription = robust.subscribe_blocks.await?;
let mut stream = subscription.into_stream;
while let Some = stream.next.await
Subscription behaviour:
- If no block arrives within
subscription_timeout, the provider automatically fails over to fallbacks. - While on a fallback, the subscription periodically attempts to reconnect to the primary provider (every
reconnect_interval). - When a fallback fails, the primary is tried first before moving to the next fallback.
- The
Laggederror indicates the consumer is not keeping pace with incoming blocks.
HTTP-based subscriptions (feature flag)
By default, subscriptions use WebSocket/pubsub-capable providers. Normally, HTTP-only providers are skipped during subscription retries. If your environment only exposes HTTP endpoints, you can enable HTTP-based block subscriptions via polling using the http-subscription Cargo feature:
[]
= { = "1.0.1", = ["http-subscription"] }
With this feature enabled and allow_http_subscriptions(true) is set, those HTTP providers can also act as subscription sources via polling, and are treated like regular pubsub-capable providers in the retry/failover logic:
let robust = new
.allow_http_subscriptions
// Optional: tune how often to poll for new blocks (defaults to ~12s)
.poll_interval
.build
.await?;
Provider Conversion
The library provides two conversion traits for flexible provider handling:
IntoRootProvider
Converts various types into an Alloy RootProvider. Implementations are provided for:
RobustProviderRootProvider&str(connection URL)UrlFillProviderCacheProviderDynProviderCallBatchProvider
IntoRobustProvider
Converts any IntoRootProvider type directly into a RobustProvider with default settings:
use IntoRobustProvider;
// Convert a URL directly to a RobustProvider
let robust: = "ws://localhost:8545".into.await?;
// Or convert an existing provider
let provider = new.connect.await?;
let robust: = provider.into.await?;
Testing
Run the test suite:
The tests use local Anvil instances to verify retry logic, failover behaviour, and subscription resilience.
Extensibility
The library exposes try_operation_with_failover, allowing you to wrap any custom logic with the full retry and failover logic:
use Provider;
// Use try_operation_with_failover to call a combination of RPC methods with full resilience
let block = robust
.try_operation_with_failover
.await?;
This gives you the same automatic retries, timeouts, and failover behaviour for any RPC method supported by your node.