Network and RPC
How SOL_NETWORK picks a cluster, how to point the runtime at your own RPC endpoints, which parts of the platform hit Solana hardest, and the knobs you 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.
- Expand the Solana card
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.
Pointing the runtime at your own RPC
The key is named for the cluster the service resolved to, not for the value
you typed. SOL_NETWORK="mainnet" reads SOL_MAINNET_RPC; "testnet" reads
SOL_TESTNET_RPC; anything else — unset, misspelled, mainnet-beta — resolves
to devnet and reads SOL_DEVNET_RPC. Get SOL_NETWORK wrong and your paid
endpoint is in a key nothing looks at, which is the same silent failure the
cluster fall-through causes on its own.
Set neither key and nothing changes: the public cluster endpoint is used exactly as before. Both keys take a list, and the two lists are concatenated.
The endpoints form a failover pool, not a preference order. It dials one it has never tried before any it has measured, and after that the fastest, with a 20% margin before it switches. So every entry must be a healthy endpoint on this cluster — one bad URL in the list is not harmless padding, it is an endpoint that will be dialled.
The requirements report shows the key for the resolved cluster and whether it is set. If you leave the public cluster in place, plan capacity around it: it applies per-IP limits and returns 429 under load, and everything below exists because that is the expected condition rather than 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. Put a dedicated endpoint in SOL_<NETWORK>_RPC,
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