Your Solana app does not query every validator. It sends JSON-RPC requests to an RPC node, which reads cluster state, simulates transactions, forwards signed bytes, and streams account changes.
That node sits on the critical path between your interface and the chain. A weak RPC setup can show stale balances, drop subscriptions, hit rate limits, or return a transaction signature that the product mistakes for confirmation.
This guide explains the boundary and gives you an RPC Readiness Checklist for production review.
RPC is the application interface to a Solana cluster
Solana validators process transactions and agree on ledger state. Applications reach that state through APIs exposed by RPC nodes.
browser or server
│
├─ HTTP JSON-RPC: read state, simulate, submit, poll
└─ WebSocket: subscribe to account, log, slot, and signature changes
│
RPC node
│
Solana clusterA typical application asks an RPC node to:
- fetch an account or balance;
- retrieve a recent blockhash;
- simulate a transaction;
- submit a signed transaction;
- check its signature status; or
- notify the client when selected state changes.
The node answers from its view of the cluster. Different RPC nodes can briefly report different slots or forks, especially at lower commitment. Treat the endpoint, cluster, requested commitment, and response context as one unit of evidence.
The endpoint cannot sign for a user or change rules enforced by an on-chain program. The client builds the request, required authorities sign the transaction, and the cluster decides whether execution succeeds.
Cluster choice changes the entire state space
Mainnet, devnet, and testnet are separate Solana clusters. Address format stays the same on each, but account data and balances can differ or be absent.
- Mainnet: persistent production network with real SOL and assets.
- Devnet: application development and testing, with faucet SOL.
- Testnet: validator and protocol testing; its ledger may reset.
Bind every environment to an explicit HTTP endpoint, WebSocket endpoint, cluster label, and explorer base URL. Switching only the RPC URL while keeping cached accounts from another cluster creates believable but false UI state.
const clusters = {
devnet: {
http: process.env.SOLANA_DEVNET_RPC_URL!,
ws: process.env.SOLANA_DEVNET_WS_URL!,
},
mainnet: {
http: process.env.SOLANA_MAINNET_RPC_URL!,
ws: process.env.SOLANA_MAINNET_WS_URL!,
},
} as const;Validate configuration at startup. A mainnet failure must not send traffic to devnet or replace private capacity with a public endpoint.
Solana's public endpoints are rate limited and explicitly not intended for production applications. They are useful for learning and light development.
At the July 21, 2026 review, the official cluster reference listed 100 requests per 10 seconds per IP, 40 requests per 10 seconds for one method, and 40 concurrent connections. The same page warns that these limits can change without notice. A deployed product needs private RPC capacity sized for its traffic and failure tolerance.
For latency-sensitive trading and data workloads, RPC Edge is our separate Solana infrastructure venture. Evaluate it against the same capacity, observability, support, and failover requirements you would apply to any production RPC provider.
Reads need both commitment and context
Each RPC read is a view of ledger state at a point in time. Commitment tells the node how much cluster confirmation the selected bank should have.
The common levels are:
- processed: the node has processed the block, but it may still be on a fork that disappears.
- confirmed: the cluster has voted on the block with the documented confirmation threshold.
- finalized: the block has reached the strongest standard commitment.
Lower commitment can surface progress sooner. Higher commitment gives stronger rollback protection. The correct choice depends on what the product will do with the answer.
A portfolio screen might display a confirmed balance and mark it as recently updated. Irreversible off-chain payouts can require finalized state plus business-level checks.
Many RPC responses include a context.slot alongside the value:
{
"jsonrpc": "2.0",
"result": {
"context": { "slot": 123456789 },
"value": 5000000000
},
"id": 1
}Keep that slot when freshness or ordering matters. A slower response from slot 123456700 should not overwrite newer state already rendered from slot 123456789.
Set minContextSlot where a method supports it when the read must come from at least a known slot. The constraint protects against moving backward after switching providers or retrying through a lagging node.
HTTP reads state, while WebSocket reports changes
HTTP methods answer one request at a time. That model fits initial page data, validation, simulation, submission, and recovery polling.
WebSocket subscriptions keep a connection open and push matching changes. Common subscriptions cover accounts, program accounts, logs, slots, and transaction signatures.
Subscriptions improve responsiveness, but they are not durable storage. Connections close. Browsers sleep. Network routes change. A client can miss updates between disconnect and resubscription.
Follow a snapshot-plus-stream pattern:
- Open the subscription or record a starting slot.
- Fetch an HTTP snapshot at a known commitment.
- Apply subscription updates only when they are newer than displayed state.
- Reconnect with bounded backoff after a disconnect.
- Fetch another HTTP snapshot to repair any missed interval.
Store the subscription ID so you can unsubscribe during cleanup. Duplicate listeners can produce duplicate notifications and slowly raise connection usage.
Browser lifecycle deserves its own test. Suspend the tab, switch networks, restore connectivity, and confirm that the UI reconciles through HTTP rather than trusting an old socket.
Submission and confirmation are separate operations
sendTransaction sends a signed transaction to an RPC node. The node performs preflight checks by default, then forwards the bytes to the cluster.
A successful RPC response means the node accepted the request and returned the transaction's first signature. It does not guarantee that the transaction landed, executed successfully, or reached the commitment your product requires.
signed transaction
│
▼
sendTransaction returns signature
│
├─ transaction may land and succeed
├─ transaction may land and fail
└─ blockhash may expire before landingThe application must track that signature with getSignatureStatuses, a signature subscription, or both. It must also retain the recent blockhash's lastValidBlockHeight so it can classify an expired transaction.
Simulation catches many deterministic errors before submission. Inspect err, program logs, compute units, and returned account data that your flow requested. A successful simulation is still not a future-state guarantee because balances and account state can change before execution.
Keep preflightCommitment aligned with the commitment used to fetch the blockhash and simulate. Mixed views can create avoidable blockhash or fork confusion.
For a complete state machine and safe rebroadcast rules, use the Solana transaction reliability runbook. The transaction guide explains message structure, fees, size, and compute.
Rate limits need an application policy
Providers can limit requests per second, concurrent connections, response bytes, method cost, or monthly credits. A single balance widget may trigger several calls after a reconnect, and public traffic can multiply that fan-out.
HTTP 429 means the client exceeded a rate limit. Respect the Retry-After header when present. Retry eligible reads with exponential backoff and jitter, then stop after a bounded attempt count.
Do not retry every error:
- Retry a transient timeout, 429, or selected 5xx response within a budget.
- Do not retry invalid parameters or a deterministic simulation failure unchanged.
- Do not rebuild and re-sign a transaction because one HTTP request timed out.
- Do not switch providers without preserving cluster, commitment, slot, and transaction identity.
Reduce load before buying more capacity. Cache immutable data, deduplicate in-flight reads, batch compatible methods, and subscribe only to accounts visible or operationally required.
Move provider credentials and high-volume reads behind a server when practical. A NEXT_PUBLIC_ endpoint is visible to every browser user. Domain restrictions can reduce casual misuse, but they do not turn a shipped credential into a secret.
Failover must preserve correctness
A second endpoint helps only when the application knows when and how to use it. Blindly racing every request increases cost and can return inconsistent views.
Define primary and secondary roles per operation. Reads can fail over with a minimum acceptable slot. Transaction submission can rebroadcast the exact same signed bytes through another endpoint while the original blockhash remains valid.
Log the endpoint, method, latency, HTTP status, RPC error code, context slot, and transaction signature. Never log private keys, seed phrases, or signed payloads unless a tightly controlled diagnostic process requires them.
Run the RPC Readiness Checklist
Review this list before directing production traffic to an endpoint:
- Cluster: Are HTTP, WebSocket, explorer, cached data, and addresses bound to the same cluster?
- Configuration: Does startup fail when a required endpoint is missing or malformed?
- Commitment: Does each read and transaction flow use a documented commitment policy?
- Freshness: Does the client retain context.slot and reject older state where ordering matters?
- Subscriptions: Can the client reconnect, resubscribe, clean up listeners, and repair gaps through HTTP?
- Submission: Does the product treat a returned signature as submitted rather than confirmed?
- Expiry: Is lastValidBlockHeight stored with each recent-blockhash transaction?
- Retries: Are retryable methods, backoff, jitter, and attempt ceilings explicit?
- Limits: Are 429, Retry-After, connection ceilings, and provider credits observable?
- Failover: Can a secondary endpoint preserve cluster, commitment, slot, and transaction identity?
- Security: Are private credentials server-side, with logs scrubbed of signing material?
- Operations: Can support trace one user action across endpoint, method, slot, signature, and final state?
Test the unhappy paths. Throttle the endpoint, close the socket, return a stale read, delay a response, and expire a blockhash. The product should show a precise state and recover without asking the user to guess what happened.
FAQ
Is an RPC node a Solana validator?
Many RPC nodes run validator software with transaction voting disabled and API services enabled. Their job is to serve application requests, index available ledger data, and forward transactions rather than participate as voting validators.
Can I use the public Solana RPC endpoint in production?
Solana's documentation says public endpoints are not intended for production. Rate limits can change, and high-traffic clients may be blocked. Choose private RPC access for a public application.
Should every read use finalized commitment?
No. Finalized gives stronger rollback protection but can surface state later. Match commitment to the consequence, then show pending state honestly where the interface needs faster feedback.
Are WebSocket subscriptions enough to keep state correct?
No. A subscription can disconnect and miss changes. Pair it with an HTTP snapshot on startup and after reconnecting.
Does switching RPC providers change the transaction signature?
Rebroadcasting the exact same signed bytes does not change the signature. Rebuilding the message with a new blockhash does, and it creates a distinct transaction attempt.
Primary references
- Solana RPC methods
- Solana clusters and public RPC endpoints
- Solana RPC JSON structures
- sendTransaction
- simulateTransaction
- Solana WebSocket methods
Review your production RPC path
Run the RPC Readiness Checklist against one live user flow. If provider design, transaction delivery, or observability remains unclear, bring the trace to the Builderz project fit form.



