Chain-agnostic load balancing + gateway for JSON-RPC endpoints.
- SDK:
LoadBalancerfor selecting/health-tracking upstream RPC endpoints - Gateway:
RpcGatewayHTTP server that forwards JSON-RPC to upstream pools (with routing rules)
Status: beta — API may evolve.
- Round-robin selection with endpoint health tracking
- Automatic failover after configurable consecutive failures
- Per-endpoint headers + optional timeouts
- Method-aware routing
- Route requests by JSON-RPC method (single or batch)
- Global method allowlist
- CORS support for browser-based clients
- ESM-first package (
"type": "module")
- Node.js: recommended >= 20 (some example dependencies expect Node 20+)
npm install rpc-load-balancerimport { LoadBalancer } from "rpc-load-balancer";
const lb = new LoadBalancer([
"https://rpc1.example.com",
"https://rpc2.example.com",
]);
// Use a rotating URL with any RPC client:
const url = lb.getUrl();
// Or send JSON-RPC directly:
const res = await lb.request({
jsonrpc: "2.0",
id: 1,
method: "getSlot",
});import { RpcGateway } from "rpc-load-balancer";
const gateway = new RpcGateway({
port: 8080,
routes: [
{
id: "default",
endpoints: ["https://rpc1.example.com", "https://rpc2.example.com"],
},
],
});
await gateway.start();
// Point your JSON-RPC client at: http://127.0.0.1:8080Endpoints can be strings or objects (see src/sdk/types.ts):
const lb = new LoadBalancer([
{ url: "https://rpc1.example.com", headers: { Authorization: "Bearer x" } },
{ url: "https://rpc2.example.com", timeoutMs: 5_000 },
]);const gateway = new RpcGateway({
port: 8080,
defaultRouteId: "default",
telegram: {
botToken: "1234567890:exampleToken",
chatId: "-1234567890",
},
routes: [
{
id: "heavy",
methods: ["getProgramAccounts", "getBlock"],
endpoints: ["https://heavy.example.com"],
},
{
id: "default",
endpoints: ["https://rpc1.example.com", "https://rpc2.example.com"],
},
],
});const gateway = new RpcGateway({
port: 8080,
allowedMethods: ["getSlot", "getBlockHeight"],
routes: [{ id: "default", endpoints: ["https://rpc.example.com"] }],
});- SDK
new LoadBalancer(endpoints, options?)getUrl(),getEndpoint(),getStatus()fetch(input, init?, methods?),request(payload, init?)createFetch(),getLastUsedEndpoint()markHealthy(idOrUrl),markUnhealthy(idOrUrl, reason?)
- Gateway
new RpcGateway(config)start(),stop(),getStatus(),getBalancer(routeId)
For the full type-level reference, see:
src/sdk/types.tssrc/gateway/types.ts
See src/example/:
npm run gateway— starts an example gatewaynpm run clientornpm run solana-client— runs Solana-specific client example against the gatewaynpm run sdk— runs an SDK example
npm install
npm run buildnpm testIssues and PRs are welcome. Please include:
- A clear description of the change and motivation
- Tests for new behavior (or an explanation if not possible)
MIT