Solana

Solana Beta is live. Try BoltRPC Solana endpoints free - start your trial now.

The Graph vs Direct RPC: When to Use Each for Blockchain Data

The Graph and direct RPC endpoints solve different problems. This guide explains when to use each, when to use both, and how to decide based on your application's actual data requirements.

BoltRPC
BoltRPC Team
9 min read
The Graph vs Direct RPC: When to Use Each for Blockchain Data

The Graph vs Direct RPC: When to Use Each for Blockchain Data

Every developer building on Ethereum eventually asks this question: should I use The Graph or direct RPC calls to get my blockchain data?

The answer is not one or the other. The Graph and RPC endpoints are tools designed for different jobs. Most production DeFi applications use both. The skill is knowing which one handles which part of your data layer.


What Each Tool Actually Does

Direct RPC (JSON-RPC) Direct RPC calls go straight to a blockchain node. You ask the node a question (what is this address’s balance, what did this contract return, what events were emitted in this block range) and the node answers using its local copy of the blockchain state.

RPC is the raw connection to the blockchain. Everything else is built on top of it.

The Graph The Graph is an indexing layer that sits between your application and the raw blockchain. Developers write “subgraphs,” configurations that tell The Graph which contracts to watch, which events to index, and how to transform that raw data into queryable entities.

Once deployed, your subgraph is continuously updated as new blocks come in. You query it via GraphQL instead of JSON-RPC.


What Direct RPC Is Good At

Current state queries

RPC is instant for reading the current state of any contract or address. No indexing required. The node has the data locally.

// Current token balance — fast, no indexing needed
const balance = await contract.balanceOf(walletAddress);

// Current pool price — direct from contract state
const [reserve0, reserve1] = await pool.getReserves();

// Any view function on any contract, any chain
const result = await contract.anyViewFunction(params);

Transaction submission and confirmation

Only RPC can submit transactions. The Graph is read-only.

// This only works via RPC
const tx = await contract.swap(amountIn, amountOutMin, path, to, deadline);
await tx.wait();

Real-time event streaming

WebSocket subscriptions give you instant notification of new events as they happen: no polling, no delay.

const wsProvider = new ethers.WebSocketProvider(WSS_ENDPOINT);
const contract = new ethers.Contract(POOL_ADDRESS, POOL_ABI, wsProvider);

// Fires instantly when a swap occurs
contract.on('Swap', (sender, amount0In, amount1In, amount0Out, amount1Out) => {
  updatePrice(amount0Out, amount1Out);
});

Simple historical queries (recent blocks)

For recent history (last few thousand blocks), eth_getLogs via RPC is fast and simple.

const logs = await provider.getLogs({
  address: TOKEN_ADDRESS,
  topics: [transferTopic],
  fromBlock: currentBlock - 1000, // last ~3 hours
  toBlock: 'latest',
});

Multi-chain, any contract

RPC works with any contract on any chain, instantly, without deployment. New contract deployed five minutes ago? Call it via RPC with no setup.


Where Direct RPC Falls Short

Deep historical queries across many blocks

eth_getLogs becomes slow and unreliable for very large block ranges. Most providers time out at 10,000–100,000 blocks per query. Scanning millions of blocks for all historical transfer events of a token requires chunking and takes significant time.

Complex data relationships

Joining data across multiple events and contracts via RPC requires application-level logic. Getting all positions for a protocol (which involves reading across multiple user interactions, fee accruals, and state changes) means dozens of calls and significant data assembly code.

Aggregated statistics

“What is the total volume of all Uniswap pools in the last 30 days?” requires processing millions of Swap events. Via RPC this means scanning millions of blocks, decoding events, aggregating values, a job that takes minutes even optimized.

Pagination and filtering

eth_getLogs does not support pagination natively. If a filter returns 10,000 events, you get all 10,000 at once. Filtering beyond topics is not possible at the RPC layer. You do it in your application after fetching.


What The Graph Is Good At

Historical data at any depth

Once a subgraph is deployed and synced, querying 3 years of historical data takes the same time as querying last week’s data. The Graph has already processed and stored it.

{
  swaps(
    where: { timestamp_gte: 1672531200 }
    orderBy: timestamp
    orderDirection: desc
    first: 1000
  ) {
    id
    timestamp
    amount0In
    amount1Out
    amountUSD
  }
}

Aggregated metrics

The Graph can compute and store aggregated values as new events arrive. TVL, volume, fee APR: pre-computed and instantly queryable.

{
  pools(orderBy: totalValueLockedUSD, orderDirection: desc, first: 10) {
    id
    token0 { symbol }
    token1 { symbol }
    totalValueLockedUSD
    volumeUSD
    feesUSD
  }
}

Complex entity relationships

Subgraphs let you define entities and relationships. A “position” entity can be built from dozens of events (mint, burn, collect, transfer) and queried as a single object.

{
  position(id: "0x...tokenId") {
    owner
    pool { token0 { symbol } token1 { symbol } }
    liquidity
    depositedToken0
    depositedToken1
    collectedFeesToken0
    collectedFeesToken1
  }
}

Pagination and filtering

GraphQL supports pagination (first, skip, after) and filtering on any indexed field. Results are already processed. No post-processing in your application.


Where The Graph Falls Short

Latency

The Graph typically has 1–5 minute latency behind the chain tip. It indexes new blocks but is never perfectly real-time. For a live price display that needs data from the last few seconds, The Graph is too slow.

Setup time

Writing, deploying, and syncing a subgraph takes hours to days. Initial sync for a full protocol history can take days or weeks. RPC is instant. No deployment required.

Cost

Querying The Graph Network costs GRT tokens. Hosted service is being deprecated. For high-query-volume applications (dashboards serving many users), The Graph query costs can be significant.

Any contract, instantly

If a protocol launches a new contract, it is immediately accessible via RPC. Adding it to a subgraph requires a subgraph update, redeployment, and potentially re-syncing.

Private or custom chains

The Graph supports a set of chains. Chains not supported require running your own Graph node, significant infrastructure. RPC works on any EVM chain instantly.


The Decision Framework

Use this to decide for each piece of data your application needs:

Question: What data do I need?

Is it current state (balance, price, contract state)?
  → YES → Direct RPC (eth_call)

Is it real-time events (watch for new swaps, transfers)?
  → YES → WebSocket subscription via RPC

Is it recent history (last few hours/days of events)?
  → YES → eth_getLogs via RPC

Is it deep historical data (months/years, millions of events)?
  → YES → The Graph

Is it aggregated stats (TVL, volume, APR)?
  → YES → The Graph

Does it involve complex entity relationships?
  → YES → The Graph

Does it need to work immediately without deployment?
  → YES → Direct RPC

Does the chain have an existing subgraph?
  → NO → Direct RPC (or build your own indexer)

Most Production DeFi Apps Use Both

A typical DeFi interface has multiple data layers, each best served by a different tool:

UI ElementData SourceWhy
Current token pricesRPC (WebSocket)Real-time, sub-second
Your current positionsRPC (eth_call)Current state, instant
Protocol TVL / volumeThe GraphHistorical aggregation
Recent swap historyRPC (eth_getLogs)Last few hours, fast
Full position historyThe GraphDeep historical data
Transaction submissionRPC onlyOnly RPC can write
30-day fee APRThe GraphPre-computed aggregation

The read-write split is absolute: everything that writes to the chain goes through RPC. The read-only split depends on freshness vs depth requirements.


When to Use Only RPC

  • Your application only needs current state (no historical data required)
  • The contract is new and has no subgraph
  • The chain is not supported by The Graph
  • You need real-time data with sub-second freshness
  • Initial sync time for a subgraph is not acceptable
  • Query costs are a concern at scale

When to Use Only The Graph

  • Your application is primarily analytics or a historical dashboard
  • You need aggregated metrics (TVL, volume, APR across time)
  • The data relationships are complex and span many events
  • An existing subgraph already covers your protocol
  • You do not need real-time data

FAQ

Is The Graph replacing RPC?

No. The Graph is an indexing layer built on top of RPC. The Graph’s own indexers use RPC to read blockchain data and build their indexes. You cannot submit transactions through The Graph, and real-time data (sub-minute freshness) always requires direct RPC.

What is a subgraph?

A subgraph is a configuration file that tells The Graph which smart contracts to watch, which events to index, and how to transform raw event data into queryable entities. Once deployed to The Graph Network, it is continuously updated as new blocks arrive.

Can I use The Graph for any chain?

The Graph supports a growing list of EVM-compatible chains including Ethereum, Arbitrum, Base, Polygon, Optimism, and others. Chains not yet supported require running your own Graph node or using alternative indexing solutions. Check thegraph.com for the current list.

What is the latency difference?

Direct RPC via WebSocket subscriptions can surface new events within seconds of a block being mined. The Graph typically lags 1–5 minutes behind the chain tip. For most analytics use cases this is acceptable. For real-time trading interfaces, it is not.

What if I need deep historical data but also real-time updates?

Use both. The Graph for historical context (position history, aggregated metrics, past performance). RPC WebSocket for real-time updates as new blocks arrive. This hybrid approach is the standard architecture for production DeFi interfaces.


BoltRPC provides JSON-RPC and WebSocket access to 20+ blockchain networks: the RPC layer your application needs for real-time reads, transaction submission, and everything The Graph does not handle.

Start your free 2-week trial: trial.boltrpc.io

Related: Ethereum RPC Methods Guide | WebSocket vs HTTP for Blockchain RPC

Frequently asked questions

Ready to build with high-performance RPC?

Start your free trial today. No credit card required. Access 20+ networks instantly.

Disclaimer: The content in this article is for informational purposes only and does not constitute financial, legal, or technical advice. Code examples and configurations are provided as-is. Always verify information with official documentation and test thoroughly in your own environment before deploying to production.

Continue reading