npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@nvana-dharma/rpc-pooler

v1.0.0

Published

A resilient RPC connection pooler for Solana that automatically retries failed requests across multiple RPC endpoints.

Readme

@nvana-dharma/rpc-pooler

A resilient RPC connection pooler for Solana that automatically retries failed requests across multiple RPC endpoints.

Why use this? Solana RPC nodes can be unreliable. This package automatically retries your requests across multiple endpoints with configurable retry strategies, so you don't have to handle failover logic yourself.

Installation

pnpm add @nvana-dharma/rpc-pooler

Quick Start

The easiest way to use the pooler is with PoolConnectionProvider, which implements common Solana Connection methods with automatic failover:

import { PoolConnectionProvider } from '@nvana-dharma/rpc-pooler'
import { ExponentialBackoffRpcPool } from '@nvana-dharma/rpc-pooler'
import { PublicKey } from '@solana/web3.js'

// Create a pool with your RPC endpoints
const pool = new ExponentialBackoffRpcPool({
  urls: [
    'https://api.mainnet-beta.solana.com',
    'https://solana-api.projectserum.com',
    'https://rpc.ankr.com/solana'
  ],
  maxRetries: 3,
  requestTimeoutMs: 5000
})

// Wrap it in a connection provider
const connection = new PoolConnectionProvider(pool)

// Use it like a regular Solana Connection
const accountInfo = await connection.getAccountInfo(
  new PublicKey('...')
)

const blockHeight = await connection.getBlockHeight('finalized')

const { blockhash } = await connection.getLatestBlockhash()

That's it! All your RPC calls now automatically retry across multiple endpoints if one fails.

Supported Methods

PoolConnectionProvider implements these commonly-used Connection methods:

  • getAccountInfo(publicKey, commitmentOrConfig?)
  • getMultipleAccountsInfo(publicKeys, commitmentOrConfig?)
  • getBlockHeight(commitment?)
  • getLatestBlockhash(commitmentOrConfig?)
  • confirmTransaction(strategy, commitment?)

Need a method that's not listed? You can use the pool directly (see Direct Pool Usage).

Configuration

Basic Options (both pool types)

{
  urls: string[]                    // Required: List of RPC endpoints
  defaultCommitment?: Commitment    // Default: 'confirmed'
  requestTimeoutMs?: number         // Default: 30000 (30 seconds)
  onError?: (url, error, attempt) => void    // Called on each failed attempt
  onDebug?: (message) => void       // Debug logging callback
}

Exponential Backoff Options

{
  maxRetries?: number        // Default: 3 - How many retry cycles
  baseDelayMs?: number      // Default: 1000 - Starting delay between retries
  maxDelayMs?: number       // Default: 30000 - Maximum delay between retries
  jitter?: boolean          // Default: true - Add randomness to delays
  shuffleOnRetry?: boolean  // Default: false - Randomize URL order on each retry
}

Choosing a Retry Strategy

This package provides two retry strategies:

SimpleRpcPool - Fast Failover

Tries each URL once in order. Fails fast if all endpoints are down.

Best for: Quick failover when you have reliable backup RPCs.

import { SimpleRpcPool } from '@nvana-dharma/rpc-pooler'

const pool = new SimpleRpcPool({
  urls: ['primary.rpc.com', 'backup1.rpc.com', 'backup2.rpc.com']
})

ExponentialBackoffRpcPool - Resilient Retry

Cycles through all URLs multiple times with increasing delays. Handles temporary outages and rate limits.

Best for: Production environments where reliability is critical.

import { ExponentialBackoffRpcPool } from '@nvana-dharma/rpc-pooler'

const pool = new ExponentialBackoffRpcPool({
  urls: ['rpc1.com', 'rpc2.com', 'rpc3.com'],
  maxRetries: 3,
  baseDelayMs: 1000,  // Start with 1 second
  maxDelayMs: 30000,  // Cap at 30 seconds
  jitter: true        // Prevent thundering herd
})

Complete Example

import {
  ExponentialBackoffRpcPool,
  PoolConnectionProvider
} from '@nvana-dharma/rpc-pooler'
import { PublicKey, LAMPORTS_PER_SOL } from '@solana/web3.js'

// Set up the pool
const pool = new ExponentialBackoffRpcPool({
  urls: [
    'https://api.mainnet-beta.solana.com',
    'https://solana-api.projectserum.com',
  ],
  maxRetries: 2,
  requestTimeoutMs: 5000,
  onError: (url, error, attempt) => {
    console.error(`Attempt ${attempt} failed for ${url}:`, error.message)
  }
})

const connection = new PoolConnectionProvider(pool)

// Fetch account balance with automatic retry
async function getBalance(pubkey: PublicKey): Promise<number> {
  const accountInfo = await connection.getAccountInfo(pubkey)
  if (!accountInfo) return 0
  return accountInfo.lamports / LAMPORTS_PER_SOL
}

// Fetch multiple accounts with automatic retry
async function getMultipleBalances(pubkeys: PublicKey[]): Promise<number[]> {
  const accounts = await connection.getMultipleAccountsInfo(pubkeys)
  return accounts.map(acc => acc ? acc.lamports / LAMPORTS_PER_SOL : 0)
}

// Usage
const wallet = new PublicKey('...')
const balance = await getBalance(wallet)
console.log(`Balance: ${balance} SOL`)

Advanced Usage

Direct Pool Usage

If you need methods not provided by PoolConnectionProvider, use the pool directly:

import { ExponentialBackoffRpcPool } from '@nvana-dharma/rpc-pooler'

const pool = new ExponentialBackoffRpcPool({ urls: [...] })

// Execute any Connection method
const result = await pool.request((connection) => {
  return connection.getSlot()
})

// Complex multi-step operations
const data = await pool.request(async (connection) => {
  const slot = await connection.getSlot()
  const blockTime = await connection.getBlockTime(slot)
  return { slot, blockTime }
})

Statistics

Monitor pool performance:

const stats = pool.getStats()

console.log(`Success rate: ${stats.successfulRequests}/${stats.totalRequests}`)

// Per-URL statistics
Object.entries(stats.urlStats).forEach(([url, urlStats]) => {
  console.log(`${url}:`)
  console.log(`  Success rate: ${urlStats.successes}/${urlStats.attempts}`)
  console.log(`  Avg response time: ${urlStats.averageResponseTime?.toFixed(0)}ms`)
})

Dynamic URL Management

Add or remove endpoints at runtime:

const pool = new SimpleRpcPool({ urls: ['https://rpc1.com'] })

pool.addUrl('https://rpc2.com')
pool.removeUrl('https://rpc1.com')

console.log(pool.getUrls())  // ['https://rpc2.com']

Error Handling

The pools automatically retry these errors:

  • Network timeouts and connection errors
  • HTTP 429 (rate limiting), 502, 503, 504 (server errors)
  • RPC internal errors

Non-retryable errors (like invalid parameters) fail immediately.

Performance Tips

  1. Order URLs by reliability - Put your most reliable RPC first
  2. Set appropriate timeouts - Balance between patience and speed (5-10 seconds is usually good)
  3. Monitor statistics - Use getStats() to identify problematic RPCs
  4. Use exponential backoff in production - Handles transient failures better
  5. Enable jitter - Prevents all clients from retrying simultaneously

Legacy API

The original RpcPooler class is still available for backward compatibility:

import { RpcPooler } from '@nvana-dharma/rpc-pooler'

const pooler = new RpcPooler(['url1', 'url2', 'url3'])
const slot = await pooler.request(
  (connection) => connection.getSlot(),
  'finalized'
)

Note: New code should use SimpleRpcPool or ExponentialBackoffRpcPool with PoolConnectionProvider instead.

License

MIT