runicRPC Logo
runicRPCv0.1
Documentation

Production Guide

Best practices for running runicRPC in production.

Configuration

Use Multiple Providers

Never rely on a single provider:

// Set API keys in .env file:
// HELIUS_API_KEY=your-key
// ALCHEMY_API_KEY=your-key
// QUICKNODE_RPC_URL=https://your-endpoint.quiknode.pro/token/

const rpc = RunicRPC.create({
  strategy: 'latency-based'
});

// Or configure explicitly
const rpc = RunicRPC.create({
  providers: {
    helius: { apiKey: process.env.HELIUS_API_KEY! },
    alchemy: { apiKey: process.env.ALCHEMY_API_KEY! },
    quicknode: {
      rpcUrl: process.env.QUICKNODE_HTTP!,
      wsUrl: process.env.QUICKNODE_WS!
    }
  },
  strategy: 'latency-based'
});

Enable Health Checks

Monitor endpoint health continuously:

const rpc = RunicRPC.create({
  healthCheck: {
    enabled: true,
    interval: 30000, // 30 seconds
    timeout: 5000,
    unhealthyThreshold: 3,
    healthyThreshold: 2,
    probeMethod: 'getHealth',    // primary health check
    probeFallback: 'getSlot'     // fallback if getHealth unavailable
  }
});

Configure Retry Logic

Set appropriate retry limits:

const rpc = RunicRPC.create({
  retry: {
    maxAttempts: 3,
    initialDelay: 100,
    maxDelay: 5000
  }
});

Monitoring

Track Events

Monitor critical events:

rpc.on('endpoint:unhealthy', (event) => {
  logger.error('Endpoint down', {
    endpoint: event.endpoint,
    reason: event.reason
  });
  sendAlert(`RPC endpoint ${event.endpoint} is unhealthy`);
});

rpc.on('circuit:open', (event) => {
  logger.warn('Circuit breaker opened', { endpoint: event.endpoint });
});

Export Metrics

Use Prometheus metrics for observability:

import express from 'express';

const app = express();

app.get('/metrics', (req, res) => {
  res.set('Content-Type', 'text/plain');
  res.send(rpc.exportPrometheusMetrics());
});

app.listen(9090);

Enhanced metrics include:

  • Latency quantiles (p50, p95, p99, avg)
  • Success rates per endpoint
  • Circuit breaker states (closed, half-open, open)
  • Cache hit rates and deduplication counts

See Events & Metrics for full details.

Get Statistics

Monitor performance:

setInterval(() => {
  const stats = rpc.getStats();
  console.log({
    totalRequests: stats.totalRequests,
    errorRate: stats.totalErrors / stats.totalRequests,
    cacheHitRate: stats.cacheHitRate,
    endpoints: stats.endpoints.map(e => ({
      name: e.name,
      latency: e.latency.avg,
      errors: e.errors
    }))
  });
}, 60000); // Every minute

Error Handling

Graceful Degradation

Handle failures gracefully:

try {
  const result = await rpc.request('getSlot');
  return result;
} catch (error) {
  if (error instanceof NoHealthyEndpointsError) {
    logger.error('All endpoints down', error.lastFailures);
    // Fallback logic or alert
  } else if (error instanceof CircuitBreakerOpenError) {
    logger.warn('Circuit breaker open', { endpoint: error.endpoint });
    // Wait and retry or use cached data
  }
  throw error;
}

Cleanup on Shutdown

Always close connections properly:

async function shutdown() {
  logger.info('Shutting down...');
  await rpc.close();
  process.exit(0);
}

process.on('SIGTERM', shutdown);
process.on('SIGINT', shutdown);

Performance Tips

Cache Configuration

Tune cache for your workload:

const rpc = RunicRPC.create({
  cache: {
    enabled: true,
    ttl: 1000, // 1 second for fast-changing data
    maxSize: 5000, // Increase for high-traffic
    cacheableMethods: ['getSlot', 'getBalance', 'getAccountInfo'] // customize cached methods
  }
});

Use Middleware for Logging

Add request/response middleware for production logging:

const rpc = RunicRPC.create({
  middleware: {
    beforeRequest: async (method, params) => {
      logger.debug('RPC request', { method, params });
      return params;
    },
    afterResponse: async (method, result) => {
      logger.debug('RPC response', { method });
      return result;
    },
    onError: async (method, error) => {
      logger.error('RPC error', { method, error: error.message });
    }
  }
});

Use Batch Requests

Reduce HTTP overhead by batching multiple requests:

// Instead of multiple individual requests
const results = await rpc.batchRequest([
  { method: 'getSlot' },
  { method: 'getBalance', params: [wallet1] },
  { method: 'getBalance', params: [wallet2] },
  { method: 'getBlockHeight' },
]);

Rate Limiting

Set per-endpoint rate limits:

const rpc = RunicRPC.create({
  endpoints: [
    {
      name: 'premium',
      rpcUrl: '...',
      rateLimit: 500 // 500 req/s
    },
    {
      name: 'standard',
      rpcUrl: '...',
      rateLimit: 100 // 100 req/s
    }
  ]
});

Connection Pooling

runicRPC automatically manages HTTP connections and WebSocket pools. No additional configuration needed.

Security

Environment Variables

Never hardcode API keys:

// ✗ Bad
const rpc = RunicRPC.create({
  providers: {
    helius: { apiKey: 'abc123...' } // Never do this!
  }
});

// ✓ Good - auto-load from .env
const rpc = RunicRPC.create();

// ✓ Also Good - explicit env vars
const rpc = RunicRPC.create({
  providers: {
    helius: { apiKey: process.env.HELIUS_API_KEY! }
  }
});

API Key Rotation

runicRPC automatically masks keys in logs, but rotate them regularly:

  1. Generate new API key from provider
  2. Update environment variable
  3. Restart application
  4. Revoke old key

Environment Variables

Configure everything via environment variables for easy deployment:

# Provider keys
HELIUS_API_KEY=your-key
ALCHEMY_API_KEY=your-key

# Core settings
RUNIC_STRATEGY=latency-based
RUNIC_LOG_LEVEL=info

# Cache settings
RUNIC_CACHE_ENABLED=true
RUNIC_CACHE_TTL=1000

# Retry settings
RUNIC_RETRY_MAX_ATTEMPTS=3

# Health check settings
RUNIC_HC_ENABLED=true
RUNIC_HC_INTERVAL=30000
RUNIC_HC_PROBE_METHOD=getHealth

See Configuration for the full list of environment variables.

Troubleshooting

See Troubleshooting Guide for common issues and solutions.