Skip to content

Architecture

RPC Plane sits between your application and your Solana RPC providers. It makes sub-millisecond routing decisions using pre-computed health scores and returns the response from the selected provider.

                    ┌──────────────────────────────────────────┐
                    │              RPC Plane                    │
                    │                                          │
  App request ─────▶│  Ingress (HTTP)                          │
                    │       │                                  │
                    │       ▼                                  │
                    │  Request Classifier                      │
                    │  (read vs write, method)                 │
                    │       │                                  │
                    │       ▼                                  │
                    │  Router ◄──── Health Scorer               │
                    │  (select provider)    ▲                  │
                    │       │               │                  │
                    │       │         Slot Tracker             │
                    │       │         (background loop)        │
                    │       ▼                                  │
                    │  ┌─────────┐  ┌─────────┐  ┌─────────┐  │
                    │  │Provider │  │Provider │  │Provider │  │
                    │  │   A     │  │   B     │  │   C     │  │
                    │  └────┬────┘  └────┬────┘  └────┬────┘  │
                    │       │            │            │        │
                    │       ▼            ▼            ▼        │
                    │  Response / Retry logic                  │
                    │       │                                  │
  App response ◄────│  Egress                                  │
                    │                                          │
                    │  Prometheus metrics ──▶ :9401/metrics    │
                    └──────────────────────────────────────────┘

Request flow

  1. Ingress — the proxy accepts the JSON-RPC request (HTTP POST).
  2. Request classifier — parses the method field and classifies it as a read or a write.
  3. Router — selects a provider (or set of providers) based on current health scores and the configured strategy.
  4. Provider call — the proxy forwards the request. For broadcasts it fans out concurrently.
  5. Retry / failover — on retryable errors (429, 5xx, timeout) the proxy tries the next provider in the ordered list.
  6. Egress — the first successful response is returned to the caller.

All steps happen in the hot path. Health scores are pre-computed by background tasks; the router reads them from a shared atomic snapshot without any blocking I/O.


Background tasks

Two independent background loops run per provider:

Health probe loop (default: every 2s)

Sends getSlot and getHealth to each provider, measures round-trip latency, tracks success/failure. Updates the rolling error rate and consecutive-failure counter. Triggers circuit state transitions.

Slot tracker loop (default: every 1s)

Polls each provider with getSlot commitment=processed and records the result. Computes the network tip (max slot across all providers) and the per-provider slot drift. Slot freshness is fed into the health score.


Health score

See Health scoring for details.


Routing strategies

See Routing for details on each strategy.


Write-path broadcast

sendTransaction and simulateTransaction are always broadcast to all healthy providers, regardless of the routing strategy.

The proxy fans out concurrently and returns the first non-error response. Duplicate submissions are harmless on Solana — the network deduplicates by signature. Broadcasting maximises the probability that at least one provider relays the transaction to the leader.


Retry logic

On a retryable error from the primary provider, the proxy tries the next provider in the ordered list (up to max_retries, default 2).

Retryable — try another provider:

  • HTTP 429, 500, 502, 503, 504
  • JSON-RPC -32003 (node not ready), -32005 (node is behind), -32603 (internal error)

Non-retryable — return immediately:

  • HTTP 400, 401, 403, 404
  • JSON-RPC -32700 (parse error), -32600 (invalid request), -32601 (method not found), -32602 (invalid params)

Hot reload

The proxy watches the config file for changes (checked every 2 seconds). When the file is modified:

  • Added providers — new health monitor and slot tracker tasks start immediately.
  • Removed providers — their background tasks are stopped.
  • URL-changed providers — treated as remove + add (resets health state).
  • Unchanged providers — accumulated health history is preserved.

server.listen and server.metrics_listen require a restart.


Key design constraints

Sub-millisecond routing. Health scores are pre-computed in background tasks and stored in a RwLock<Arc<...>> snapshot. The router reads the snapshot and makes an O(N) sort — no I/O in the hot path.

No unbounded state. Error rate uses a fixed sliding window. Slot history is a single atomic integer per provider. Memory usage is constant under sustained load.

No single point of failure. All panic paths are caught at the request handler level. One bad request or provider response cannot crash the proxy.

Zero mandatory infrastructure. Everything runs in-process. No external databases, caches, or service dependencies.