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:
- Generate new API key from provider
- Update environment variable
- Restart application
- 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.