If you're new to Solana RPC, the endpoint URL looks like a magic string. There's actually structure to it — auth schemes, query parameters, and patterns for choosing between providers — that affects how reliable your code is in production. Once you understand the pieces, swapping providers, debugging connection issues, and adding redundancy all get easier.
This piece is a reference for Solana RPC endpoints: URL structure, the auth options, the methods you'll use most, and the production patterns that distinguish a working setup from a fragile one.
What an RPC Endpoint Is
A Solana RPC endpoint is an HTTPS URL that accepts JSON-RPC requests. Sample format:
https://your-provider.example/?api-key=YOUR_KEY
Or:
https://your-name.your-provider.example
The shape varies by provider, but the protocol is the same: HTTP POST with a JSON-RPC body.
For WebSocket subscriptions, providers usually expose a parallel wss:// endpoint:
wss://your-provider.example/?api-key=YOUR_KEY
Both endpoints typically come from the same provider; you'll use HTTP for most read/write operations and WebSocket for subscriptions.
Authentication Patterns
Three common schemes:
Query parameter API key.
https://provider.example/?api-key=YOUR_KEY
Simple to set up, easy to test in browser. Works with all standard SDKs because the URL is passed through to HTTP requests.
Path-embedded API key.
https://provider.example/YOUR_KEY
Same idea, different URL shape. Most SDKs handle both.
Header-based auth.
const connection = new Connection("https://provider.example", {
httpHeaders: {
"Authorization": "Bearer YOUR_TOKEN",
},
});
More secure (key not in URL strings, doesn't get logged in HTTP server logs as easily). Some providers offer this; not all SDKs handle it cleanly out of the box.
For most use cases, query parameter or path-embedded is fine. Header-based matters more if you have audit/compliance requirements.
Public Endpoints vs Provider Endpoints
Solana itself exposes public endpoints:
https://api.mainnet-beta.solana.com— public mainnethttps://api.devnet.solana.com— public devnethttps://api.testnet.solana.com— public testnet
These are rate-limited, have no SLA, and lag behind real network state during congestion. Use them for development and tutorials only. Anything in production goes through a provider.
For mainnet production, you want a provider URL. Providers run their own RPC fleets with capacity, monitoring, and SWQoS support. The trade-off is that you're paying (or running into a free tier limit), but the difference in reliability and performance is large.
Common RPC Methods
A reference of the methods you'll actually use most:
Reads:
// Account state
connection.getAccountInfo(pubkey, "confirmed");
connection.getMultipleAccountsInfo([key1, key2, key3], "confirmed");
// Balances
connection.getBalance(pubkey, "confirmed");
connection.getTokenAccountBalance(tokenAccountKey, "confirmed");
// Token holdings
connection.getTokenAccountsByOwner(ownerKey, { programId: TOKEN_PROGRAM_ID });
// Transaction history
connection.getSignaturesForAddress(pubkey, { limit: 10 });
connection.getTransaction(signature, "confirmed");
// Network state
connection.getLatestBlockhash("confirmed");
connection.getSlot("confirmed");
connection.getEpochInfo("confirmed");
// Program interactions
connection.getProgramAccounts(programId, { filters: [...] });
Writes:
connection.sendTransaction(tx, signers, options);
connection.sendRawTransaction(serialised, options);
Subscriptions (WebSocket):
connection.onAccountChange(pubkey, callback, "confirmed");
connection.onLogs(programId, callback, "confirmed");
connection.onSignature(signature, callback, "confirmed");
Simulation:
connection.simulateTransaction(tx, signers);
For the full list, see Solana's JSON-RPC reference. The above covers ~95% of what most applications use.
Production Patterns
Patterns that work in production:
Separate read and write endpoints. As covered in earlier pieces, read RPC and write RPC have different optimisation profiles. Use different providers for each.
const readConnection = new Connection(READ_RPC_URL, "confirmed");
const writeConnection = new Connection(WRITE_RPC_URL, "processed");
Use environment variables. Don't hardcode URLs:
const RPC_URL = process.env.SOLANA_RPC_URL;
if (!RPC_URL) throw new Error("SOLANA_RPC_URL not set");
Configure timeouts explicitly:
const connection = new Connection(RPC_URL, {
commitment: "confirmed",
confirmTransactionInitialTimeout: 30_000,
fetchMiddleware: yourFetchMiddleware, // optional, for logging/auth
});
Handle rate limiting: All production RPCs rate-limit. Implement client-side retry with exponential backoff for 429 responses. Don't crash on rate limits.
Use connection pooling for high-volume reads: If you're doing thousands of reads per second, multiple Connection instances can help (some HTTP clients open separate connections per Connection instance).
Don't reuse signing connections across users: A Connection wraps an HTTP client. For multi-tenant applications, isolate connection state per user/request to avoid leaking tokens.
Failover and Redundancy
For high-availability deployments:
Active-passive failover. Primary RPC; secondary RPC kicks in on detected failures. Doable with a wrapper around Connection that detects errors and switches.
Read fan-out. Send the same read query to multiple RPCs; use whichever responds first. Simple to implement; doubles your read traffic.
Write redundancy is harder. Sending the same transaction to multiple RPCs can result in duplicate execution if both succeed. Generally not worth doing for sends; pick one good RPC.
Health checks. Periodically ping each RPC's /health or getHealth method. Switch to a healthy one if your primary fails.
For most teams, active-passive with a single primary is enough. Full multi-region active-active is overkill until you're at significant scale.
Common URL Issues
Things that go wrong:
Trailing slashes. Some SDKs are picky. https://provider.example and https://provider.example/ may behave differently.
Path components vs query params. Make sure the provider's documentation matches your URL structure.
HTTP vs HTTPS. Always HTTPS in production. Don't trust a provider that gives you an HTTP-only endpoint.
WebSocket URL derivation. Some libraries derive WebSocket URLs from HTTP URLs. If your provider's WebSocket endpoint is at a different path, you may need to set it explicitly.
Encoding API keys. API keys with special characters need URL-encoding. Most providers issue keys without special chars, but be aware.
CORS for browser clients. Some providers don't allow browser-origin requests. If you're calling RPC from a browser, verify CORS is configured.
Checking RPC Health
A quick health check pattern:
async function isHealthy(connection) {
try {
const slot = await Promise.race([
connection.getSlot("processed"),
new Promise((_, reject) => setTimeout(() => reject(new Error("timeout")), 3000)),
]);
return slot > 0;
} catch (e) {
return false;
}
}
If your RPC returns a slot quickly, it's probably working. More sophisticated checks include comparing the returned slot against a reference value (to detect lag).
For production, also check:
- Recent blockhash freshness (compare
getLatestBlockhashagainst expected timing) - Transaction simulation succeeds (catch broken state)
- Subscription connection establishes cleanly (catch WebSocket issues)
What to Do This Week
If you're setting up Solana RPC for a project:
- Pick a provider for both read and write (can be the same or different).
- Use environment variables for URLs. Don't hardcode.
- Configure connection timeouts explicitly, don't rely on defaults.
- Implement rate-limit handling with exponential backoff.
- Health-check your RPCs in your monitoring.
- Plan for failover at least at the active-passive level.
- Test the WebSocket endpoint if you're using subscriptions — it's often a separate URL.
Try BoltTx for Production Endpoints
BoltTx provides a production-grade write RPC:
https://bolttx.io/?api-key=YOUR_API_KEY
Drop-in:
import { Connection } from "@solana/web3.js";
const writeConnection = new Connection(
"https://bolttx.io/?api-key=YOUR_API_KEY",
"processed"
);
Single global endpoint with internal smart routing — no region selection, no DevOps overhead. Native Anti-MEV routing. Sub-second confirmation as a design floor. Per-signature delivery telemetry.
Free tier signup. Pair with whatever read provider you prefer.
FAQ
Can I use the public Solana RPC for production? No. It's rate-limited, has no SLA, and lags during congestion. Use a provider.
What's the difference between mainnet-beta and mainnet? Same network, different naming convention. "mainnet-beta" is the formal name; "mainnet" is informal usage. They refer to the same chain.
Should I use one RPC or multiple? For development, one. For production, often two — one for reads, one for writes. Each optimised for its role.
How do I rotate an API key? Provision a new key, update your environment, deploy. Rotate keys periodically as a security practice.
Are Solana RPC endpoints standardised? The JSON-RPC method names are standardised. URL structure and auth schemes vary by provider. Code that uses standard SDK methods works with any compliant provider.