A high-performance, production-ready RPC load balancer built in Rust that supports multiple blockchain networks with automatic health checking and failover capabilities.
- Multi-Network Support: Ethereum, Base, Arbitrum (easily extensible)
- Round-Robin Load Balancing: Lock-free atomic counter-based distribution
- Health Monitoring: Asynchronous health checks using
eth_blockNumberJSON-RPC - Automatic Failover: Intelligent endpoint selection skipping unhealthy RPCs
- Path-Based Routing: Route requests by network via URL path (e.g.,
/ethereum,/base) - Request Metrics: Per-network atomic counters for total/success/failure tracking
- Graceful Shutdown: Proper signal handling for clean termination
- Comprehensive Logging: Detailed tracing of endpoint selection, health transitions, and request timing
Client Request
↓
HTTP Proxy Server (Hyper)
↓
Path Parser (/ethereum, /base, /arbitrum)
↓
Round-Robin Load Balancer
↓
Health Check Filter (skip unhealthy endpoints)
↓
Request Forwarding to Selected RPC
↓
Response Streaming Back to Client
- Config Module: TOML-based configuration with environment override support
- State Module: Shared application state with
Arc<RwLock<>>for health status - Health Check Module: Background tasks checking endpoints every N seconds
- Load Balancer: Atomic counter-based round-robin selection
- Proxy Module: HTTP request forwarding with header filtering
- Metrics Module: Lock-free atomic counters for observability
[server]
port = 8080
[health_check]
interval_secs = 30
[networks.ethereum]
endpoints = [
"https://eth.llamarpc.com",
"https://rpc.ankr.com/eth"
]
[networks.base]
endpoints = [
"https://mainnet.base.org",
"https://base.llamarpc.com"
]Create a .env file for overrides (optional):
# Override config.toml values with RPC_ prefix
RPC_SERVER__PORT=9000
RPC_HEALTH_CHECK__INTERVAL_SECS=60
# Set logging level
RUST_LOG=debugcargo build --releasecargo run --releaseOr run the binary directly:
./target/release/rpc-swarmSend JSON-RPC requests to the proxy with the network in the path:
# Ethereum request
curl -X POST http://localhost:8080/ethereum \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "eth_blockNumber",
"params": [],
"id": 1
}'
# Base request
curl -X POST http://localhost:8080/base \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "eth_blockNumber",
"params": [],
"id": 1
}'- Each endpoint is checked every
interval_secs(default: 30s) - Health check uses
eth_blockNumberJSON-RPC call - Endpoints are marked unhealthy after 3 consecutive failures
- Endpoints recover immediately on successful health check
- Health transitions are logged for visibility
Set the RUST_LOG environment variable to control log levels:
RUST_LOG=info cargo run # Info and above
RUST_LOG=debug cargo run # Debug and above
RUST_LOG=trace cargo run # All logsLogged events:
- Endpoint selection for each request
- Request duration in milliseconds
- Health status transitions (healthy ↔ unhealthy)
- HTTP errors and failures
rpc-swarm/
├── Cargo.toml # Dependencies and project metadata
├── config.toml # Network and server configuration
├── .env.example # Example environment variables
├── src/
│ ├── main.rs # Server initialization and shutdown
│ ├── config.rs # Configuration loading and validation
│ ├── state.rs # Shared application state
│ ├── error.rs # Custom error types
│ ├── metrics.rs # Atomic counter metrics
│ ├── health_check.rs # Background health monitoring
│ ├── load_balancer.rs # Round-robin endpoint selection
│ └── proxy.rs # HTTP request forwarding
└── README.md
- hyper 1.0: HTTP server and client
- tokio: Async runtime
- reqwest: Health check HTTP client
- serde: Configuration serialization
- config: TOML configuration parsing
- tracing: Structured logging
- Add network configuration to
config.toml:
[networks.polygon]
endpoints = [
"https://polygon-rpc.com",
"https://polygon.llamarpc.com"
]- Restart the server - the network is automatically detected and initialized
This project follows conventional commits for learning purposes:
feat(module): description- New featuresfix(module): description- Bug fixesrefactor(module): description- Code improvementsdocs: description- Documentation updates
- Lock-Free Operations: Round-robin counter uses
AtomicUsizewithOrdering::Relaxed - Read-Heavy Optimization: Health status uses
RwLock(multiple readers, single writer) - Async I/O: Non-blocking request handling with Tokio
- Connection Pooling: Hyper client reuses connections
- Zero-Copy: Body streaming without buffering
NoHealthyEndpoints: Returns 503 Service UnavailableNetworkNotFound: Returns 404 Not FoundInvalidPath: Returns 400 Bad Request- HTTP forwarding errors: Returns 502 Bad Gateway
MIT
This is a learning project demonstrating Rust async patterns, HTTP proxying, and production-ready architecture. Feel free to fork and experiment!