How to set up multi-provider RPC failover for Ethereum
A single RPC provider is a single point of failure. If that provider goes down, rates you, or starts serving stale data, your application stops working correctly. Multi-provider failover mitigates this. You route requests to a backup provider when the primary fails.
This page shows how to set up a multi-provider failover system using ethers.js or viem. It covers health checks, retry logic, cost considerations, and decentralized fallback options.
Client-side failover with ethers.js or viem
Both libraries let you create multiple JsonRpcProvider or Provider instances. The basic idea is to wrap them in a custom function that tries one, and on failure, tries the next.
With ethers.js, you write a simple fallback provider:
import { ethers } from 'ethers';
const providers = [
new ethers.JsonRpcProvider('https://mainnet.infura.io/v3/YOUR_KEY'),
new ethers.JsonRpcProvider('https://eth-mainnet.alchemyapi.io/v2/YOUR_KEY'),
new ethers.JsonRpcProvider('https://rpc.ankr.com/eth'),
];
async function withFailover(method, params) {
for (const provider of providers) {
try {
return await provider.send(method, params);
} catch (error) {
console.warn(`Provider failed: ${error.message}`);
continue;
}
}
throw new Error('All providers failed');
}
Viem uses a similar pattern with its createPublicClient and fallback transport:
import { createPublicClient, http, fallback } from 'viem';
import { mainnet } from 'viem/chains';
const client = createPublicClient({
chain: mainnet,
transport: fallback([
http('https://mainnet.infura.io/v3/YOUR_KEY'),
http('https://eth-mainnet.alchemyapi.io/v2/YOUR_KEY'),
http('https://rpc.ankr.com/eth'),
]),
});
Viem's fallback transport handles failover automatically. It reorders providers based on latency and retries on failure.
Health check strategies
Not all failures are crashes. A node can be alive but serving stale or forked data. An unsynced node returns blocks with outdated state. You must detect this.
The simplest health check asks for the latest block number from each provider and compares them. If one provider's block number lags more than a few blocks behind the median, mark it unhealthy. A practical threshold is 5-10 blocks for mainnet Ethereum (a block every 12 seconds).
async function checkProviderHealth(provider) {
try {
const blockNumber = await provider.getBlockNumber();
return { healthy: true, blockNumber };
} catch {
return { healthy: false, blockNumber: null };
}
}
For forked chain detection, check that the block hash matches the majority. Query the block at height N from all providers. If one returns a different hash, it may be on a fork. Exclude it.
Retry logic with exponential backoff
Simple retries risk hammering a failing provider. Exponential backoff spreads out retries. Start with a 100ms delay, double it each attempt, cap at 5 seconds.
async function retryWithBackoff(fn, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
if (attempt === maxRetries - 1) throw error;
await new Promise(resolve => setTimeout(resolve, 100 * 2 ** attempt));
}
}
}
Combine this with the failover loop. Retry on one provider before switching to the next.
Cost and load distribution
Running multiple provider subscriptions costs money. Each paid tier charges for compute units, requests, or storage. You pay for redundant traffic.
One strategy: route 80% of requests to the cheapest provider, 20% to the backup. This reduces cost while keeping the backup warm. For read-heavy dapps, caching common queries (like token balances or prices) cuts request volume across all providers.
A load balancer proxy sits between your app and providers. It distributes traffic based on rules you define. Tools like HAProxy or Envoy can health-check backend RPCs and route around failures. This adds operational complexity but centralizes failover logic.
Client-side failover is simpler to deploy but harder to coordinate across many users. Each client independently detects failures. If a provider has a global outage, all clients failover at once. A proxy can react faster.
Decentralized fallback options
Pocket Network and other decentralized RPC networks offer an alternative. These networks aggregate node operators. You pay for relay requests with their token or through a gateway. They act as a fallback when centralized providers fail.
The tradeoffs are latency and reliability. Decentralized networks can be slower than dedicated providers. Their node set varies. But they are resilient to single-provider censorship or downtime.
You can add a Pocket Network gateway as the last entry in your provider list. It serves as a catch-all.
For most applications, the combination of two major providers plus a decentralized fallback covers the common failure modes. Start with viem's fallback transport. Add health checks for stale blocks. Use exponential backoff. Keep the design simple. Complexity is its own failure mode.
Not financial advice. starname.me publishes market data and general information about digital assets. Crypto assets are volatile and you can lose everything you put in. Nothing here is a recommendation to buy, sell or hold, and we make no price predictions.
Prices are sourced from third parties and may be delayed or wrong. Verify anything you intend to act on against a primary source.