Configuration Reference¶
RPC Plane is configured via a TOML file (default: rpc-plane.toml in the current directory).
Run rpc-plane init to generate a starter file. Use -c /path/to/config.toml to specify a different path.
Environment variable interpolation: any value can reference env vars:
url = "https://mainnet.helius-rpc.com/?api-key=${HELIUS_API_KEY}"
url = "https://endpoint.quiknode.pro/$QUICKNODE_KEY" # braces optional
Unset variables expand to an empty string. The proxy validates provider URLs on startup and will warn if any are empty.
[server]¶
[server]
listen = "127.0.0.1:9400" # address for the proxy (JSON-RPC endpoint)
metrics_listen = "127.0.0.1:9401" # address for Prometheus metrics + /health
| Key | Default | Description |
|---|---|---|
listen |
"127.0.0.1:9400" |
TCP address the proxy listens on. Change to 0.0.0.0 to expose on all interfaces. |
metrics_listen |
"127.0.0.1:9401" |
Metrics and health endpoint. Serves GET /metrics (Prometheus) and GET /health (JSON). |
Note
server.listen and metrics_listen require a restart to change — they are not hot-reloaded.
[health]¶
Controls how providers are probed and scored.
[health]
interval_ms = 2000 # probe each provider this often
window_secs = 60 # sliding window for error rate
slot_drift_threshold = 10 # slots behind tip → drifting
slot_interval_ms = 1000 # slot tracker poll interval
circuit_open_failures = 5 # consecutive failures → circuit open
circuit_error_threshold = 0.5 # error rate threshold → circuit open
circuit_cooldown_secs = 30 # wait before half-open probe
# Score weights (auto-normalised, do not need to sum to 1)
w_latency = 0.4
w_error = 0.3
w_slot = 0.2
w_success = 0.1
Probe settings¶
| Key | Default | Description |
|---|---|---|
interval_ms |
2000 |
How often (ms) to send a getSlot + getHealth probe to each provider. |
window_secs |
60 |
Sliding window (seconds) over which error rate is computed. |
slot_drift_threshold |
10 |
Slots behind network tip before slot freshness score drops to 0. |
slot_interval_ms |
1000 |
How often (ms) the slot tracker polls each provider with getSlot processed. |
Circuit breaker¶
| Key | Default | Description |
|---|---|---|
circuit_open_failures |
5 |
Consecutive probe failures that trip the circuit open. |
circuit_error_threshold |
0.5 |
Rolling error rate threshold (0.0–1.0) that opens the circuit. |
circuit_cooldown_secs |
30 |
Seconds before attempting a half-open probe after the circuit opens. |
Health score weights¶
| Key | Default | What it controls |
|---|---|---|
w_latency |
0.4 |
Round-trip latency component |
w_error |
0.3 |
Error rate component |
w_slot |
0.2 |
Slot freshness component |
w_success |
0.1 |
Recent probe success rate |
See Health scoring for the full formula.
[routing]¶
[routing]
strategy = "best_score" # routing strategy for reads
max_retries = 2 # retries on transient errors
cost_aware = false # enable cost_efficiency_score weight
cost_weight = 0.2 # w_cost when cost_aware = true
| Key | Default | Description |
|---|---|---|
strategy |
"best_score" |
Read routing strategy. See Routing strategies. |
max_retries |
2 |
Maximum provider retries on retryable errors (HTTP 429/5xx, RPC -32003/-32005/-32603). |
cost_aware |
false |
When true, adds a cost efficiency component to the score. Requires [providers.pricing]. |
cost_weight |
0.2 |
Weight of the cost efficiency score when cost_aware = true. |
[[providers]]¶
At least one provider is required. Add multiple [[providers]] blocks for multi-provider routing.
[[providers]]
name = "helius"
url = "https://mainnet.helius-rpc.com/?api-key=${HELIUS_API_KEY}"
weight = 1
[[providers]]
name = "quicknode"
url = "https://your-endpoint.quiknode.pro/${QUICKNODE_API_KEY}"
weight = 1
| Key | Required | Default | Description |
|---|---|---|---|
name |
Yes | — | Unique identifier. Used in logs and metric labels. |
url |
Yes | — | Full HTTP URL including API key. Supports env var interpolation. |
weight |
No | 1 |
Relative weight for weighted_random strategy. No effect on other strategies. |
[providers.pricing]¶
Optional cost tracking. Enables cost-aware routing when routing.cost_aware = true.
[[providers]]
name = "helius"
url = "https://mainnet.helius-rpc.com/?api-key=${HELIUS_API_KEY}"
[providers.pricing]
model = "credits"
monthly_budget_usd = 200
| Key | Description |
|---|---|
model |
Pricing model: "credits", "compute_units", or "flat". |
monthly_budget_usd |
Monthly budget cap in USD. |
[reporting]¶
Sends telemetry to a remote endpoint. Absent by default — the proxy runs with no outbound connections.
[reporting]
endpoint = "http://localhost:3000/api/ingest"
api_key = "rp_live_xxxx"
flush_interval_ms = 5000
| Key | Description |
|---|---|
endpoint |
HTTP endpoint to POST telemetry batches to. |
api_key |
Bearer token sent with each batch. |
flush_interval_ms |
How often to flush the event buffer (ms). |
Full example¶
[server]
listen = "127.0.0.1:9400"
metrics_listen = "127.0.0.1:9401"
[health]
interval_ms = 2000
window_secs = 60
slot_drift_threshold = 10
circuit_open_failures = 5
circuit_error_threshold = 0.5
circuit_cooldown_secs = 30
w_latency = 0.4
w_error = 0.3
w_slot = 0.2
w_success = 0.1
[routing]
strategy = "best_score"
max_retries = 2
[[providers]]
name = "helius"
url = "https://mainnet.helius-rpc.com/?api-key=${HELIUS_API_KEY}"
weight = 1
[[providers]]
name = "quicknode"
url = "https://your-endpoint.quiknode.pro/${QUICKNODE_API_KEY}"
weight = 1
[[providers]]
name = "triton"
url = "https://your-pool.rpcpool.com/${TRITON_API_KEY}"
weight = 1