What Is RPC?
RPC (Remote Procedure Call) is the communication protocol that allows applications to interact with a blockchain node. When your wallet shows your ETH balance, when a DeFi protocol executes a swap on Uniswap, or when a block explorer displays the latest transactions — all of these interactions happen through RPC calls. RPC is the bridge between the user-facing world of applications and the decentralized world of blockchain nodes.
In simple terms, RPC lets your application say to a blockchain node: “Tell me the balance of this address,” “Send this transaction,” or “What is the latest block number?” The node processes the request and returns the result. Your application never needs to run a full blockchain node itself — it can delegate all the heavy lifting to an RPC provider.
How Ethereum RPC Works
Ethereum uses JSON-RPC 2.0, a protocol where requests and responses are formatted as JSON objects. The communication typically happens over HTTP or WebSocket connections. A standard RPC request looks like this:
{
"jsonrpc": "2.0",
"method": "eth_getBalance",
"params": ["0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18", "latest"],
"id": 1
}
And the response:
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x56bc75e2d63100000"
}
The result is in hexadecimal (wei), which converts to approximately 100 ETH. Every interaction between a dApp and the blockchain follows this request-response pattern.
Key JSON-RPC Methods
The Ethereum JSON-RPC API exposes hundreds of methods. Here are the most important ones:
Reading state (eth_ namespace):
eth_getBalance(address, block): Returns the ETH balance of an address in wei.eth_getTransactionCount(address, block): Returns the number of transactions sent from an address (the nonce).eth_getCode(address, block): Returns the bytecode at an address (empty for EOAs, contains compiled code for contracts).eth_call(txObject, block): Simulates a contract call without executing it — used for “dry-running” transactions and reading contract state.eth_getBlockByNumber(number, fullTransactions): Returns a block by its number.eth_getTransactionByHash(hash): Returns a transaction by its hash.eth_getLogs(filter): Returns log entries matching a filter — used to query contract events.
Writing transactions (eth_ namespace):
eth_sendRawTransaction(signedTx): Submits a signed transaction to the network for inclusion in a block.eth_estimateGas(txObject): Estimates the gas required for a transaction — used by wallets to set the gas limit.
Subscriptions (WebSocket only):
eth_subscribe("newHeads"): Notifies when a new block is mined.eth_subscribe("pendingTransactions"): Notifies when a new pending transaction enters the mempool.eth_subscribe("logs", filter): Notifies when contract events matching the filter are emitted.
RPC Providers
Running a full Ethereum node requires significant hardware (terabytes of storage, fast internet, constant syncing) and ongoing maintenance. Most developers and applications use RPC providers — companies that maintain fleets of nodes and expose them through a managed API. The major providers include:
Alchemy: One of the largest Ethereum infrastructure providers, used by most major DeFi protocols and NFT platforms. Offers enhanced APIs for transaction history, NFT metadata, token balances, and gas estimation beyond the standard JSON-RPC spec. Their NFT API and enhanced APIs save developers from building complex indexers.
Infura: Owned by ConsenSys, Infura has been the default Ethereum RPC provider since the early days. Free tier supports basic JSON-RPC calls, paid tiers offer higher rate limits, dedicated nodes, and archive access. Used by MetaMask as the default provider.
QuickNode: Offers both shared and dedicated nodes with global distribution. Known for competitive pricing and support for over 20 chains. Provides enhanced APIs for NFTs, tokens, and DeFi positions.
Ankr: Decentralized RPC network with nodes distributed across many providers. Offers a free public endpoint for basic use and enterprise plans for high-throughput applications.
Flashbots Protect: A specialized RPC endpoint that routes transactions through Flashbots’ private relay, protecting users from MEV (Maximal Extractable Value) attacks like front-running and sandwich attacks.
HTTP vs WebSocket RPC
HTTP RPC is stateless — each request opens a new connection, gets a response, and closes. This is fine for one-off queries like checking a balance. However, it cannot efficiently handle real-time updates.
WebSocket RPC maintains a persistent connection and supports subscriptions. You can subscribe to new blocks, pending transactions, and contract events, and the server will push notifications as they happen. This is essential for applications that need real-time data, such as:
- Trading bots monitoring mempool for arbitrage opportunities
- Wallet UIs that update balances in real-time
- Block explorers that show new blocks as they are produced
- Indexers that track contract events
Archive vs. Full Nodes
Standard full nodes keep only the current state — they know the latest balances and contract storage but cannot tell you what a balance was at a specific past block. Archive nodes store every historical state, allowing queries like “what was the USDC balance of this address at block 15,000,000?”
Archive nodes require significantly more storage (multiple terabytes for Ethereum mainnet) and are more expensive to run. RPC providers typically charge extra for archive access. If your dApp needs to read historical state (for things like calculating past portfolio values, auditing old transactions, or reconstructing event history), you need an archive node.
Rate Limits and Best Practices
RPC providers enforce rate limits to prevent abuse and ensure fair access. Exceeding these limits will result in HTTP 429 (Too Many Requests) errors. Best practices include:
- Batch requests: Use
JSON-RPC batchto send multiple method calls in a single HTTP request, reducing the number of round trips. - Caching: Cache responses that do not change frequently (contract code, ABI, block headers) on your server.
- Subscription deduplication: When using WebSocket subscriptions, avoid subscribing to the same event multiple times across different connections.
- Fallback providers: Configure multiple RPC endpoints so your application fails over if one provider is down or rate-limiting you.
- Respect rate limits: Implement exponential backoff and queuing for requests that exceed rate limits rather than hammering the endpoint.
Common Pitfalls
- Single provider dependency: If your only RPC provider goes down, your entire dApp breaks. Always configure fallback endpoints.
- Using the wrong network: Submitting a transaction signed for mainnet to a testnet RPC (or vice versa) will fail or worse, succeed on the wrong network with real funds.
- Ignoring WebSocket cleanup: Unclosed WebSocket connections leak resources and can cause memory issues in long-running applications.
- Trusting RPC providers implicitly: A compromised or malicious RPC node can return incorrect data. For security-critical operations, consider running your own node or verifying data from multiple sources.
- Not handling reorgs: On PoW chains, blocks can be reorganized. Design your application to handle potential chain reorgs gracefully, especially for financial applications.