Network and RPC
How SOL_NETWORK picks a cluster, why the runtime cannot be pointed at a paid RPC, which parts of the platform hit Solana hardest, and the knobs you actually have when the public cluster starts rate-limiting.
Every other chain family in Ecosystem takes an RPC URL. Solana does not. The
connection is constructed from SOL_NETWORK alone, resolved to the public
cluster endpoint for that cluster, and cached on a singleton for the life of the
process. This page is about what follows from that.
Cluster selection
SOL_NETWORK |
Cluster | Endpoint the service uses |
|---|---|---|
mainnet |
mainnet-beta | https://api.mainnet-beta.solana.com |
testnet |
testnet | https://api.testnet.solana.com |
| anything else | devnet | https://api.devnet.solana.com |
The third row is not a fallback you were told about. Unset, misspelled,
lowercased differently, or set to mainnet-beta — which is the cluster's real
name and the value most people reach for — all resolve to devnet. There is no
exception thrown and no log line in the request path.
The consequence is total but invisible: addresses are generated for devnet keys, the deposit monitor subscribes to devnet, and a customer's mainnet SOL sits at an address the platform is not watching on a network it is not connected to. The funds are not lost — the keypair is the same on every cluster — but nothing will credit them until the cluster is corrected.
Run Admin → Ecosystem → Blockchains → Requirements and read the Cluster resolution line. It prints the resolved endpoint, which is the only statement in the product that cannot be misread.
The two network variables
The requirements report raises a warning when the two disagree, because the stored metadata then records a cluster the address is not on. That is a diagnosis problem rather than a money problem, but it is the kind of disagreement that makes an incident take twice as long.
Why there is no custom RPC
SOL_<NETWORK>_RPC — for example SOL_MAINNET_RPC — is checked by the
Ecosystem overview badge to decide whether to draw a chain as configured. The
Solana service does not read it. Setting it makes a badge look right while
changing nothing, which is the worst possible combination, and the requirements
report labels it display-only for exactly that reason.
So: buying a Helius, QuickNode or Triton endpoint and putting it in .env does
not move your traffic. There is no supported way to redirect the runtime short
of editing backend/src/blockchains/sol.ts, which puts you outside the upgrade
path.
The public cluster applies per-IP limits and returns 429 under load. Everything below exists because that is the expected condition, not an exceptional one.
What hits Solana hardest
Four parts of the platform generate Solana RPC traffic, in roughly descending order of cost.
Transaction history. Opening a Solana transaction list fetches the last 50 signatures for the address and then fetches each transaction individually — 51 calls for one page view. Results are cached in Redis for 30 minutes per address, so the second view is free and the twenty-ninth is too. It also only parses System Program transfers, so an SPL-only address renders rows with an empty counterparty and a zero amount; that is a display limitation of this view, not a sign that the deposit was missed.
Live deposit monitoring. While a user has a deposit page open, the platform holds a WebSocket subscription for their address. Native SOL uses a logs subscription on the account; SPL uses a token-program account subscription filtered to the mint and owner. Both self-cancel after one hour of no activity, and both are torn down once a deposit is credited — the next page visit re-arms a fresh one.
The background deposit scanner. Addresses seen on a deposit page stay in a working set for 72 hours and are re-scanned on a schedule. Each Solana pass fetches the last 25 signatures for the address, or for the token account on the SPL side, and inspects the ones it has not already credited.
Withdrawals. Each one costs a fee probe, a balance read, a broadcast, a confirmation wait and then up to ten verification polls with a growing backoff. The withdrawal queue enforces a 5-second cooldown per chain between transactions, so Solana withdrawals are serialised whatever the queue depth.
The mitigations already in the code
You do not need to configure these; you need to recognise their symptoms.
- Transaction fetches are de-duplicated and cached. Concurrent lookups of the same signature share one request, and a successful result is held for 60 seconds. Several monitors observing the same deposit therefore cost one call, not several.
- Native deposit tracking retries up to 30 times, roughly every 5 seconds
with jitter, waiting for a just-seen signature to become fetchable at
finalizedcommitment. A deposit that takes a couple of minutes to credit under load is this working, not failing. - Withdrawal verification retries ten times with a 2-, 4-, 6-second …
backoff capped at 10 seconds, and treats "broadcast but unverifiable" as
TIMEOUTrather thanFAILED. See Withdrawals and fees for why that distinction protects your float. - The scanner is paced by a token bucket at 0.5 Solana address scans per second by default. When more addresses are active the sweep takes longer; the request rate does not rise. Detection latency degrades gracefully instead of the whole chain 429ing.
What you can actually tune
These are Ecosystem-wide scanner settings, not Solana-specific ones, but Solana is the chain most likely to make you reach for them.
Raising ECOSYSTEM_SCAN_RATE_SOL is the one that will bite. The default is
conservative because the anonymous cluster quota is shared with every other
anonymous client; pushing it produces 429s, which the scanner logs and skips
past, which looks exactly like deposits going missing.
Lowering ECOSYSTEM_SCAN_ACTIVE_TTL_MS reduces load in direct proportion to how
many stale addresses you stop watching, and is usually the safer lever.
Degradation, in the order you will see it
- Transaction history goes stale or empty first. It is the most expensive read and the most tolerant of failure, and it is cached for half an hour, so a bad minute shows up as an odd-looking list rather than an error.
- Live detection stops before background detection does. The subscription side is a WebSocket; the scanner side is plain HTTP. If the cluster's WebSocket endpoint is refusing you, deposits still credit — just on the scanner's cadence rather than instantly, and only for addresses that have been on a deposit page.
- Withdrawal confirmation gets slower, then uncertain. The retries absorb
a lot. Past that, a broadcast transaction that cannot be verified is parked
as
TIMEOUTfor a human to resolve, which is a queue that needs watching. - Withdrawal broadcasts start failing. At this point the cluster is rejecting you outright and the queue backs up behind the 5-second cooldown.
If you are consistently at stage 3, you are past what this integration is sized for on the public cluster. Reduce the working set, lengthen the scan interval, and be honest with yourself about Solana volume before it becomes a support queue.
Related
- Deposits — the two detection paths in detail
- Withdrawals and fees — what the retries protect
- Environment reference — every variable named here
- Troubleshooting — devnet fall-through and 429 symptoms