RPC Providers
Every code example in this guide that talks to Solana - reading a balance, sending a transaction, subscribing to account changes - does it through an RPC endpoint. This tutorial explains what that endpoint actually is, why the https://api.devnet.solana.com URL used throughout the examples is not what production apps use, and how to switch to a dedicated provider like Helius or QuickNode.
What Is an RPC Provider?
Solana itself has no single "front door." The network is a set of independent validators, each running software (Agave) that can answer questions like "what's this account's balance?" or accept a new transaction. RPC stands for Remote Procedure Call - it's the protocol your code uses to ask a validator (or a node built specifically to answer these questions) to do something.
An RPC endpoint is just a URL that points at one of these nodes. When your code calls createSolanaRpc("https://api.devnet.solana.com"), it is not talking to "Solana" in the abstract - it is talking to one specific server that happens to be running RPC software for the devnet cluster.
api.devnet.solana.com and api.mainnet-beta.solana.com are public endpoints that the Solana Foundation runs for free, for anyone. They are genuinely useful for learning and for the first few days of a project. They are shared by every developer in the world hitting them at the same time.
An RPC provider is a company that runs its own fleet of high-performance RPC nodes and gives you a private URL to reach them. Instead of sharing a queue with every other developer on the public endpoint, your app gets its own lane, with limits sized to what you are paying for.
Two of the most widely used RPC providers in the Solana ecosystem are Helius and QuickNode. Both give you a signup flow, a dashboard, and a personal RPC URL (often with an API key baked into it) within a couple of minutes.
This distinction - public shared endpoint versus dedicated provider endpoint - is the single most common thing that trips up developers moving from "it works in my tutorial" to "it works for real users."
Key Terms
| Term | Plain-language meaning |
|---|---|
RPC | Remote Procedure Call - the protocol your code uses to ask a Solana node to do something (read data, submit a transaction). |
RPC endpoint / RPC URL | The specific web address your client library sends RPC requests to. |
RPC provider | A company that runs dedicated RPC infrastructure and sells you private access to it. |
Public RPC | A free, shared endpoint (like api.devnet.solana.com) run by the Solana Foundation, with no guarantees. |
Rate limit | The maximum number of requests you're allowed to send in a given time window before requests start failing. |
API key | A secret string a provider issues you, either as part of your RPC URL or as a header, to identify and meter your usage. |
Websocket endpoint | A separate URL (wss://...) used for real-time subscriptions, like watching an account for changes. |
Enhanced API | Provider-specific endpoints beyond raw Solana RPC - e.g. indexed NFT data, webhooks, or priority-fee estimation. |
Why It Matters
The examples throughout this guide use https://api.devnet.solana.com because it requires no signup and works for anyone following along. That is exactly why it is unsuitable for a real application: it is rate-limited, has no uptime guarantee, and can throttle or reject your requests with no warning if enough other developers are hitting it at once.
Professional Solana developers treat the RPC endpoint the same way they'd treat a database connection string - as a piece of production infrastructure, not a hardcoded constant. They sign up with a dedicated provider, get a private URL, and read it from an environment variable.
Beyond reliability, dedicated providers often expose functionality the raw public RPC does not: faster indexing, webhooks that notify your backend when something happens on-chain, priority-fee estimation, and APIs tailored to specific workloads like NFTs or DeFi. Helius, for instance, offers a Digital Asset Standard (DAS) API for querying compressed NFTs and token data far more efficiently than raw RPC calls would allow.
For a hobby project or your first few days learning Solana, the public endpoint is genuinely fine. The moment you're building something other people will actually use, budget ten minutes to set up a provider - it's usually free at low volume.
Step-by-Step Walkthrough
Step 1: Recognize the endpoint this guide has been using
Look back at any code example in this guide that creates an RPC client - for instance the one in Clusters & Networks. It points at the public devnet endpoint.
import { createSolanaRpc } from "@solana/kit";
// This is the free, shared, public endpoint - fine for learning
const rpc = createSolanaRpc("https://api.devnet.solana.com");That URL is a placeholder for "any working devnet RPC endpoint," not a recommendation to ship with it. The next steps replace it with a provider-issued URL without changing anything else about how the code works.
Step 2: Sign up with Helius
Helius is an infrastructure company built specifically for Solana. Alongside standard RPC, it offers enhanced APIs for NFT and token data, webhooks for on-chain events, and priority-fee estimation.
To get a URL, create a free account at helius.dev, then open the dashboard and create a new project. Helius generates a personal RPC URL for you, with your API key embedded as a query parameter, for both devnet and mainnet-beta.
https://devnet.helius-rpc.com/?api-key=YOUR_API_KEYStep 3: Sign up with QuickNode
QuickNode is a multi-chain infrastructure provider - it supports Solana alongside Ethereum, Bitcoin, and many other networks, so it's a common choice for teams already using it elsewhere. It offers dedicated RPC nodes, an add-on marketplace for extra functionality, and usage dashboards.
To get a URL, create a free account at quicknode.com, create a new Solana endpoint from the dashboard, and pick the cluster (devnet or mainnet-beta) you need. QuickNode gives you a full HTTPS URL with your access token embedded in the path.
https://your-endpoint-name.solana-devnet.quiknode.pro/YOUR_TOKEN/You only need one provider to follow the rest of this guide - pick whichever fits your workflow, or use the public endpoint for now and swap in a provider URL later using the same pattern.
Step 4: Store the URL as an environment variable
Never hardcode a provider URL directly in source - it usually contains your API key, and committing it to git leaks that key to anyone with repo access.
# .env (add .env to .gitignore before committing anything)
SOLANA_RPC_URL=https://devnet.helius-rpc.com/?api-key=YOUR_API_KEYStep 5: Read the endpoint from configuration instead of hardcoding it
With the URL in an environment variable, swap the hardcoded string for a lookup that falls back to the public endpoint when no provider is configured - useful for local scripts and CI where you don't want to require a paid key.
import { createSolanaRpc } from "@solana/kit";
const endpoint = process.env.SOLANA_RPC_URL ?? "https://api.devnet.solana.com";
const rpc = createSolanaRpc(endpoint);The rest of your code - every rpc.getBalance(), rpc.sendTransaction(), and so on - is unchanged. Only the URL creation changes.
Putting It Together
// rpc-client.ts - Solana Kit 7.0.0
import { createSolanaRpc } from "@solana/kit";
// Falls back to the public devnet endpoint when SOLANA_RPC_URL is unset,
// so this still works for anyone cloning the repo without a provider key.
const endpoint = process.env.SOLANA_RPC_URL ?? "https://api.devnet.solana.com";
const rpc = createSolanaRpc(endpoint);
const { value: version } = await rpc.getVersion().send();
console.log("Connected via:", endpoint.includes("devnet.solana.com") ? "public devnet" : "dedicated provider");
console.log("Agave version:", version["solana-core"]);// rpc_client.rs - solana-client 3.0.10
use solana_client::rpc_client::RpcClient;
use std::env;
fn main() {
let endpoint = env::var("SOLANA_RPC_URL")
.unwrap_or_else(|_| "https://api.devnet.solana.com".to_string());
let rpc = RpcClient::new(endpoint.clone());
let version = rpc.get_version().unwrap();
println!("Connected via: {endpoint}");
println!("Agave version: {}", version.solana_core);
}Both snippets do the same thing: check for a provider URL first, and only fall back to the public endpoint if none is set. That one ?? (TypeScript) or unwrap_or_else (Rust) is the entire difference between a script that works for a demo and one that's ready to be deployed.
Nothing else in your application code needs to know or care which provider you're using - createSolanaRpc and RpcClient::new accept any valid Solana RPC URL, public or provider-issued.
Common Beginner Mistakes
- Hardcoding
api.devnet.solana.comin application code - it works until traffic picks up, then requests start silently failing under rate limits. Fix: read the endpoint from an environment variable with a public-endpoint fallback, as shown above. - Committing an API key to git - a provider URL with an embedded key is a secret, and GitHub history keeps it forever even after you delete it. Fix: put the URL in
.env, add.envto.gitignorebefore your first commit, and rotate the key if it ever leaks. - Mixing clusters between your RPC URL and your keypair - pointing a mainnet-beta provider URL at devnet-only accounts returns "account not found," not a helpful error. Fix: double-check the cluster in both your provider dashboard and your RPC URL match the accounts you're using.
- Assuming a free-tier provider plan has unlimited requests - free tiers are far more generous than the public endpoint, but they still meter requests per month or per second. Fix: check your provider's dashboard for current usage before assuming rate limits aren't the cause of a failure.
- Using the HTTPS RPC URL for real-time subscriptions -
onAccountChange-style subscriptions need a websocket connection, not a plain HTTPS request. Fix: use thewss://endpoint your provider issues alongside the HTTPS one; most SDKs accept both and pick the right one automatically. - Forgetting devnet and mainnet-beta need separate provider URLs and separate keys in most dashboards - reusing one blindly across environments makes usage impossible to attribute. Fix: create a distinct endpoint per cluster in your provider's dashboard.
FAQs
Is the public RPC endpoint bad, or just not for production?
Just not for production. api.devnet.solana.com is a legitimate, free way to learn and prototype. The problem is only that it's shared by everyone and has no uptime guarantee - fine for a tutorial, risky for anything real users depend on.
Do I need to pay for Helius or QuickNode to follow this guide?
No. Both offer free tiers that are more generous than the public endpoint and are enough for development and small projects. You only need to pay once your traffic outgrows the free tier.
What does "RPC" actually stand for?
Remote Procedure Call. It's a general programming pattern - not Solana-specific - for calling a function that runs on a different machine as if it were local.
Can I use Helius for mainnet and QuickNode for devnet, or do I have to pick one?
You can mix providers freely per cluster or per environment. Nothing in the Solana protocol ties you to a single provider - you're just choosing which company's servers answer your RPC calls.
What is an "enhanced API" and do I need one?
It's functionality a provider adds on top of raw Solana RPC - Helius's DAS API for NFT/token data is one example. You don't need one for basic reads and transactions; they matter once you're building features raw RPC makes slow or awkward, like querying every NFT a wallet owns.
Why does my provider dashboard show separate URLs for devnet and mainnet-beta?
Because they're different clusters with different data. A devnet URL only ever sees devnet accounts and transactions; you need a mainnet-beta URL (and usually a separate key) once you deploy for real.
Is a websocket endpoint the same thing as an RPC endpoint?
Related but distinct. The HTTPS RPC endpoint handles one-off requests (get a balance, send a transaction). The websocket endpoint (wss://...) handles subscriptions - your code stays connected and receives pushed updates, like "this account just changed."
What happens if I exceed my provider's rate limit?
Requests start returning errors (commonly HTTP 429) instead of data. Most SDKs don't retry automatically, so your application code needs to handle that failure - back off and retry, or surface an error to the user.
Should I put my RPC URL in client-side (browser) code?
Only if the URL and key are meant to be public-facing - check your provider's docs, since some plans support domain-restricted keys specifically for this. Otherwise, keep the URL server-side and have your backend proxy RPC calls, the same way you'd protect any other API key.
Are there RPC providers besides Helius and QuickNode?
Yes - Triton and others also serve the Solana ecosystem. Helius and QuickNode are covered here because they're the two most commonly reached for by developers new to choosing a provider, not because they're the only options.
Does switching RPC providers ever require changing my application code?
No, as long as you're reading the URL from configuration rather than hardcoding it (Step 5 above). Swapping providers becomes a one-line change to an environment variable.
Related
- Clusters & Networks - devnet, testnet, mainnet-beta, and matching your RPC URL to the right cluster
- Solana Basics - first steps on devnet using the public endpoint
- Wallets & Explorers - devnet workflow and faucets
Stack versions: This page was written for Agave 4.1.1, Solana CLI 3.0.10, @solana/kit 7.0.0, and solana-client 3.0.10 (Rust).