Writing
Web3 Dashboard: Polling, Caching vs Real-Time
When to poll, when to cache, and when to use WebSockets for on-chain data. Trade-offs between speed, cost, and accuracy with practical examples using RPCs, The Graph, and TanStack Query.
Web3 Dashboard Updates: Polling vs Caching vs Real-Time
Why Live On-Chain Data Is Hard
Blockchains are append-only ledgers, not real-time databases. Every piece of data you show — balances, prices, transaction status — is a snapshot that can become stale after it renders.
RPC nodes have rate limits. Indexers can lag behind the chain head by seconds or minutes. Price APIs can also throttle requests.
The engineering challenge is not simply fetching data once. It is deciding how fresh each data type needs to be, how much infrastructure cost you can afford, and what UX trade-offs your users will accept.
Why Blockchain Data Becomes Stale
Different Web3 data sources update at different speeds.
-
Blockchain state changes when new transactions are confirmed
-
RPC providers have request limits
-
Indexers need time to process new blocks
-
Price APIs update at different intervals
-
Cached data can remain available after the source changes
This means a dashboard needs a deliberate data freshness strategy.
When to Use Polling
Polling is the default choice for many Web3 dashboards.
It is simple, predictable, and works with almost any data source.
Recommended Polling Intervals
A practical starting point is:
-
Token balances: 30–60 seconds
-
Portfolio values: 30–60 seconds
-
Pending transaction status: 3–5 seconds
-
Protocol TVL: 60–120 seconds
// hooks/useProtocolTVL.ts
import { useQuery } from '@tanstack/react-query';
export function useProtocolTVL() {
return useQuery({
queryKey: ['protocol-tvl'],
queryFn: async () => {
const res = await fetch('/api/tvl');
return res.json() as Promise<{
tvl: number;
updatedAt: string;
}>;
},
staleTime: 60_000,
refetchInterval: 120_000,
refetchIntervalInBackground: false,
});
}
Polling on Mobile Devices
Use refetchIntervalInBackground: false when possible to reduce unnecessary network activity and battery usage.
You can also increase polling intervals during periods when users are less active.
When to Use Caching
Caching is ideal for data that does not change frequently.
Examples include:
-
Token metadata
-
Contract ABIs
-
Historical charts
-
Static protocol configurations
-
Documentation data
Server-Side Caching with Next.js
Next.js can cache server-side data so repeated requests do not always reach the upstream provider.
// app/api/token-metadata/route.ts
import { unstable_cache } from 'next/cache';
const getTokenMetadata = unstable_cache(
async (address: string) => {
const res = await fetch(
`https://api.etherscan.io/api?module=token&action=tokeninfo&contractaddress=${address}`
);
return res.json();
},
['token-metadata'],
{
revalidate: 3600,
}
);
export async function GET(request: Request) {
const address = new URL(request.url)
.searchParams.get('address')!;
const data = await getTokenMetadata(address);
return Response.json(data, {
headers: {
'Cache-Control':
's-maxage=3600, stale-while-revalidate=7200',
},
});
}
Use Multiple Cache Layers
A production dashboard can use several caching layers:
-
React Query: Client-side caching with
staleTimeandgcTime -
Next.js: Server-side caching
-
CDN: Edge caching for public API responses
Each layer reduces the amount of work required by the layer below it.
When Real-Time Updates Matter
WebSockets or Server-Sent Events (SSE) make sense when sub-second updates genuinely affect user decisions.
Examples include:
-
Live trading interfaces
-
Mempool monitoring
-
Auction countdowns
-
Block-by-block event feeds
-
Real-time market interfaces
Using WebSockets for Live Blocks
// hooks/useLiveBlocks.ts
import { useEffect, useState } from 'react';
import {
createPublicClient,
webSocket,
} from 'viem';
import { mainnet } from 'viem/chains';
const wsClient = createPublicClient({
chain: mainnet,
transport: webSocket(
process.env.NEXT_PUBLIC_ALCHEMY_WS_URL!
),
});
export function useLiveBlocks() {
const [latestBlock, setLatestBlock] = useState<
bigint | null
>(null);
useEffect(() => {
const unwatch = wsClient.watchBlocks({
onBlock: (block) =>
setLatestBlock(block.number),
});
return () => unwatch();
}, []);
return latestBlock;
}
Do You Need WebSockets for Every Dashboard?
No.
For most dashboards, polling every 15–30 seconds can provide most of the UX benefit without the additional infrastructure and connection complexity of WebSockets.
Polling vs Caching vs Real-Time Updates
| Approach | Latency | Cost | Complexity | Best For |
|---|---|---|---|---|
| Polling (30s) | Medium | Low | Low | Portfolio dashboards |
| Aggressive polling (3s) | Low | High | Low | Pending transactions |
| CDN + server cache | High | Very low | Medium | Static protocol data |
| The Graph | Medium | Medium | Medium | Historical events |
| WebSocket RPC | Very low | High | High | Trading interfaces |
Balance Freshness With Infrastructure Cost
Showing data that is 45 seconds old with a clear "Last updated 45s ago" indicator can be better than making a portfolio tracker poll every second.
The goal is not maximum freshness.
The goal is appropriate freshness at a reasonable infrastructure cost.
Common Web3 Data Sources
Different data sources are suited to different dashboard requirements.
RPC Nodes
Providers such as Alchemy, Infura, and QuickNode provide direct access to blockchain data.
They are useful for:
-
Wallet balances
-
Contract state
-
Transaction status
-
Real-time blockchain reads
Batch multiple reads with multicall and cache results where appropriate.
The Graph
The Graph provides indexed blockchain events through GraphQL.
It works well for:
-
Transaction history
-
DEX swaps
-
Governance votes
-
Historical protocol activity
Use pagination when querying large datasets.
query GetSwaps(
$pool: String!
$first: Int!
$skip: Int!
) {
swaps(
where: { pool: $pool }
orderBy: timestamp
orderDirection: desc
first: $first
skip: $skip
) {
id
timestamp
amount0In
amount1Out
sender
}
}
Moralis and Alchemy APIs
Higher-level APIs can simplify access to:
-
NFT metadata
-
Token transfers
-
Wallet history
-
Blockchain activity
These services can be useful for MVPs before investing in a custom indexing infrastructure.
DeFiLlama and CoinGecko
These sources can provide price, market, and TVL information.
Cache price and market data for approximately 30–60 seconds depending on the requirements of your application.
Avoid making individual price requests inside loops.
Recommended Data Freshness Strategy
Instead of treating every piece of dashboard data the same, divide it into freshness tiers.
Tier 1: Instant Data
Target freshness: 0 seconds
Use this for:
-
Wallet connection state
-
User-initiated transaction status
-
Signing state
-
Wallet changes
Tier 2: Near-Real-Time Data
Target freshness: 15–30 seconds
Use this for:
-
Token balances
-
Portfolio values
-
Recent wallet activity
Tier 3: Periodic Data
Target freshness: 1–5 minutes
Use this for:
-
Protocol TVL
-
Market capitalization
-
Historical charts
-
General protocol metrics
Tier 4: Static Data
Target freshness: Hours or longer
Use this for:
-
Token metadata
-
Contract ABIs
-
Documentation
-
Static protocol configurations
Choose the Cheapest Strategy That Meets the Requirement
Each freshness tier should use the simplest infrastructure that provides the required user experience.
Do not use WebSockets for data that can comfortably be refreshed through polling or caching.
Web3 Dashboard Performance Checklist
Use these practices when designing a dashboard update strategy.
Configure staleTime Per Data Type
Do not use one global staleTime for every query.
Balances, prices, protocol metrics, and static metadata can all have different freshness requirements.
Use Query Keys for Invalidation
Use predictable query keys so related data can be invalidated after a successful transaction.
Prefetch Data
Prefetch important dashboard queries during navigation or other appropriate interactions so data is ready when users reach the next screen.
Show Cached Data During Refetching
Do not replace the entire dashboard with a loading spinner every time data refreshes.
Show cached data immediately and use an isFetching indicator to communicate that an update is happening.
Rate-Limit API Routes
Protect your own API routes from excessive requests so one user or component cannot consume your upstream provider limits.
Monitor RPC Usage
Monitor RPC usage in production.
A single unbatched loop can generate thousands of requests and quickly exhaust provider limits.
FAQ About Web3 Dashboard Data Updates
How Often Should I Poll Balances?
For most display-focused dashboards, polling every 30–60 seconds is a reasonable starting point.
For active trading applications, shorter intervals such as 10–15 seconds may be appropriate.
Is The Graph Still Relevant in 2026?
Yes. The Graph remains useful for historical indexed blockchain data.
For custom indexing requirements or lower-latency applications, alternatives such as Ponder, Envio, or direct RPC with caching may be worth considering.
Should I Use React Query or SWR?
TanStack Query is a strong choice for Web3 applications because it provides extensive caching, refetching, mutation support, developer tools, and integration with wagmi.
How Should I Handle Data After a Transaction?
Invalidate the related query keys after a successful transaction.
Then refetch important data such as:
-
Wallet balances
-
Token balances
-
Transaction history
-
Portfolio values
This helps the interface reflect the latest state without forcing a complete page reload.
How Should I Handle Offline Users?
Display the last cached data and clearly communicate that it may be outdated.
TanStack Query's gcTime can keep cached data available during short periods of disconnection.
Final Thoughts
Web3 dashboards do not need every piece of data to update in real time.
The better approach is to understand how frequently each type of data changes and match it with the right strategy.
Use polling for predictable updates, caching for slow-changing data, indexers for historical information, and WebSockets only when real-time updates genuinely improve the user experience.
A well-designed freshness strategy reduces RPC costs, improves performance, and gives users data that feels both fast and trustworthy.