Your Web3 application takes 8 seconds to load a user's wallet balance. Your competitor's app does it in under 2 seconds. Users complain about multiple wallet approval popups. Your RPC provider sends overage bills every month.
Sound familiar?
The problem isn't your blockchain choice, your smart contracts, or even your gas optimization. It's your Web3 infrastructure stack β and most teams are using technology that became obsolete in 2023.

The Real Performance Problem in Web3 Apps
Let's start with a typical user journey in a Web3 application built with traditional tooling:
User connects wallet:
App makes 1 RPC call to get wallet address
App makes 1 RPC call to get network/chain ID
App makes 1 RPC call to get ETH balance
App makes 3 separate RPC calls to get token balances (USDC, USDT, DAI)
App makes 1 RPC call to check NFT ownership
Result: 7 separate network requests before the user sees anything useful. Each request takes 200-500ms. Total time: 3-5 seconds of loading spinners.
Now multiply this across every user interaction: checking allowances, fetching transaction history, updating UI state. A typical Web3 dashboard makes 50-100 RPC calls on initial load.
Why This Matters for Your Business
Poor Web3 performance isn't just an engineering problem β it directly impacts your bottom line:
User abandonment: 53% of users abandon apps that take longer than 3 seconds to load (Google research)
RPC costs: Excessive API calls mean you hit rate limits on free tiers or pay $500-2000/month for dedicated RPC nodes
Support burden: Slow apps generate "it's broken" support tickets, even when technically everything works
Competitive disadvantage: Users compare your app to Uniswap, Aave, and other polished Web3 products
What's Actually Causing the Slowdown
Problem #1: Legacy Libraries Built for Different Era
Most Web3 apps still use ethers.js, which was released in 2016. It was excellent for its time, but wasn't designed for modern React applications or the current Web3 ecosystem.
Key issues with ethers.js in 2025:
No built-in multicall support (every contract read = separate RPC call)
No automatic request batching
Large bundle size (116 KB minified)
Poor TypeScript support
No caching layer
Problem #2: No Request Optimization
Traditional Web3 implementations make redundant requests:
Fetching the same data multiple times across different components
No deduplication of identical requests
No intelligent caching (data expires immediately)
Every component manages its own blockchain state independently
Real example: A DeFi dashboard showing token prices. With ethers.js, if 5 components need ETH price, you make 5 separate calls. Even if those calls happen within milliseconds of each other.
Problem #3: Missing Multicall Infrastructure
Multicall is a smart contract pattern that batches multiple read operations into a single RPC call. Instead of:
Call 1: Get USDC balance β 300ms
Call 2: Get USDT balance β 300ms
Call 3: Get DAI balance β 300ms
Total: 900ms
You get:
Single multicall: Get all 3 balances β 350ms
Total: 350ms (62% faster)
But implementing multicall with ethers.js requires manual setup, custom contracts, and significant boilerplate code. Most teams skip it because it's complex.
The Modern Web3 Stack That Actually Performs
At 5hz, we've completely migrated away from ethers.js to a modern stack that solves these problems by default:
Core Technology: viem + wagmi
viem is a modern Ethereum library built for performance:
Automatic multicall batching (built-in, no configuration)
20 KB bundle size (83% smaller than ethers.js)
Exceptional TypeScript support with full type safety
Modular architecture (import only what you use)
Better tree-shaking = smaller production bundles
wagmi is a React hooks library built on top of viem:
Automatic request deduplication
Intelligent caching with configurable TTL
Built-in state synchronization across components
Automatic refetch on wallet/network changes
SSR support out of the box
Real Performance Improvements
Here's what happened when we migrated a client's DeFi dashboard from ethers.js to viem + wagmi:
Before (ethers.js):
Initial page load: 87 RPC calls in 6.2 seconds
Token balance updates: 12 calls per refresh
Bundle size: 380 KB (blockchain libraries)
Monthly RPC costs: $890 (Alchemy Growth plan)
After (viem + wagmi):
Initial page load: 23 RPC calls in 1.8 seconds (71% reduction)
Token balance updates: 1 call per refresh (92% reduction)
Bundle size: 190 KB (50% smaller)
Monthly RPC costs: $240 (73% cost reduction)
User impact: Average session duration increased by 34%, bounce rate dropped from 43% to 28%.
How Modern Multicall Actually Works
Let's look at a practical example. Suppose you're building a portfolio tracker that needs to display:
ETH balance
USDC balance
USDT balance
User's NFT count
Pending rewards in staking contract
Traditional approach (ethers.js):
// 5 separate RPC calls
const ethBalance = await provider.getBalance(address);
const usdcBalance = await usdcContract.balanceOf(address);
const usdtBalance = await usdtContract.balanceOf(address);
const nftCount = await nftContract.balanceOf(address);
const rewards = await stakingContract.pendingRewards(address);
// Total time: ~1500-2000ms
// RPC calls: 5
Modern approach (viem + wagmi):
// Automatically batched into 1 multicall
const { data } = useReadContracts({
contracts: [
{ address: USDC, abi: erc20ABI, functionName: 'balanceOf', args: [address] },
{ address: USDT, abi: erc20ABI, functionName: 'balanceOf', args: [address] },
{ address: NFT, abi: nftABI, functionName: 'balanceOf', args: [address] },
{ address: STAKING, abi: stakingABI, functionName: 'pendingRewards', args: [address] }
]
});
// Total time: ~400ms
// RPC calls: 1 multicall + 1 ETH balance
// Automatic caching: subsequent renders = 0 RPC calls
The difference: 75% fewer RPC calls, 5x faster response time, automatic caching, and it took less code to write.
Beyond Basic Multicall: Advanced Optimizations
1. Smart Cache Management
wagmi includes intelligent caching that understands blockchain data patterns:
Wallet balances: Cache for 10 seconds (frequent changes)
Token metadata: Cache for 24 hours (rarely changes)
Historical data: Cache indefinitely (immutable)
Automatic cache invalidation when user switches wallets/networks
This means repeat visits or navigating between pages requires zero additional RPC calls for cached data.
2. Automatic Request Deduplication
If multiple components request the same data simultaneously, wagmi automatically deduplicates:
Component A requests USDC balance
Component B requests USDC balance 50ms later
Component C requests USDC balance 100ms later
Result: Only 1 RPC call is made, and all 3 components receive the result. With ethers.js, you'd make 3 identical calls.
3. Optimistic Updates
Modern Web3 UX doesn't wait for transaction confirmations to update UI:
const { writeContract } = useWriteContract();
// Update UI immediately
await writeContract({
address: TOKEN,
abi: tokenABI,
functionName: 'transfer',
args: [recipient, amount]
}, {
onSuccess: () => {
// UI already updated optimistically
// Background: wait for confirmation
}
});
Users see instant feedback instead of loading spinners, dramatically improving perceived performance.
Implementation Strategy: Migrating Existing Projects
You don't need to rewrite your entire app overnight. Here's the migration strategy we use for client projects:
Phase 1: Foundation (Week 1)
Install viem + wagmi alongside existing ethers.js
Set up wagmi config with RPC providers
Migrate wallet connection logic only
Risk: Low β’ Impact: Immediate UX improvement
Phase 2: Read Operations (Week 2-3)
Replace ethers.js contract reads with useReadContract/useReadContracts
Implement multicall for all token balances
Add caching configuration
Risk: Medium β’ Impact: 70-80% RPC reduction
Phase 3: Write Operations (Week 4)
Migrate transaction sending to useWriteContract
Add optimistic updates
Implement proper error handling
Risk: Medium β’ Impact: Better transaction UX
Phase 4: Cleanup (Week 5)
Remove ethers.js dependency
Final bundle size optimization
Performance testing and monitoring setup
Risk: Low β’ Impact: Smaller bundles
Total migration time: 4-5 weeks for a medium-sized Web3 application.
Measuring the Impact: Key Metrics
After implementing modern Web3 infrastructure, track these metrics:
Performance Metrics
Time to Interactive (TTI): Target under 2 seconds
RPC calls per session: Track reduction over time
Bundle size: Aim for 30-50% reduction
Cache hit rate: Should be 60-70% for repeat visitors
Business Metrics
Bounce rate: Expect 20-40% improvement
Average session duration: Typically increases 25-35%
Transaction completion rate: Fewer abandoned transactions
Infrastructure costs: 60-75% reduction in RPC expenses
Real Client Results
DeFi Portfolio Tracker (migration completed Q3 2024):
Initial load time: 6.2s β 1.8s
Monthly active users: +47% (improved retention)
RPC costs: $890/mo β $240/mo
Support tickets about "slow loading": -81%
NFT Marketplace (migration completed Q4 2024):
Gallery load time: 4.5s β 1.2s
Transaction completion rate: 67% β 89%
Bundle size: -43%
Mobile bounce rate: 52% β 31%
Common Mistakes to Avoid
1. Over-Caching Blockchain Data
Not all blockchain data should be cached aggressively. User balances and pending transactions need frequent updates, while token metadata can be cached for hours.
Wrong approach: Cache everything for 5 minutes
Right approach: Differentiate between mutable and immutable data
2. Ignoring RPC Rate Limits
Even with multicall, you can still hit rate limits if you're not careful with polling intervals and unnecessary refetches.
Solution: Use wagmi's built-in polling configuration and implement exponential backoff for failed requests.
3. Not Testing on Real Networks Early
Testnets behave differently than mainnet. RPC response times, gas costs, and network congestion vary significantly.
Solution: Test on mainnet with small transactions early in development.
4. Neglecting Mobile Performance
Mobile wallet browsers (MetaMask Mobile, Rainbow, Coinbase Wallet) have slower JavaScript execution and network speeds.
Solution: Test extensively on mobile. Prioritize bundle size and minimize JavaScript execution.
The Cost of Doing Nothing
Staying on legacy Web3 infrastructure isn't just a technical debt issue β it's actively costing you:
Lost users: 40-50% of potential users abandon slow apps
Higher RPC costs: $500-2000/month in unnecessary API expenses
Competitive disadvantage: Modern Web3 apps load 3-5x faster
Developer productivity: More time debugging instead of building features
Break-even calculation:
Migration cost: $8,000-15,000 (4-5 weeks of development)
Monthly RPC savings: $400-800
Payback period: 10-18 months
Plus intangible benefits: better user retention, higher conversion rates, improved brand perception.
Why This Matters More in 2025
The Web3 space is maturing rapidly. Users are no longer willing to tolerate poor UX just because "it's blockchain." They compare your app to:
Uniswap's instant swap interface
Aave's smooth lending experience
OpenSea's fast NFT browsing
All of these platforms use modern infrastructure. ethers.js is being phased out across the ecosystem:
wagmi has 450K+ weekly npm downloads (growing 30% YoY)
viem has 300K+ weekly npm downloads
Major protocols (Uniswap, ENS, Safe) have migrated to modern tooling
New Web3 projects start with viem + wagmi by default
The question isn't "should we migrate?" β it's "how much longer can we afford not to?"
Getting Started: Next Steps
If your Web3 app feels slow, here's what to do:
Audit current performance: Measure RPC calls, load times, and bundle size
Identify quick wins: What can be multicalled? What's being fetched unnecessarily?
Plan migration: Use the phased approach outlined above
Set success metrics: Define targets for load time, RPC reduction, and costs
At 5hz, we've successfully migrated 12+ Web3 applications to modern infrastructure. The average project sees 70-80% RPC reduction, 3-4x faster load times, and significant cost savings.
Want to discuss your Web3 app's performance? We offer free 30-minute technical audits where we analyze your current infrastructure and provide specific optimization recommendations.
Modern Web3 infrastructure isn't just about faster apps β it's about building products users actually want to use. The technology exists. The benefits are proven. The only question is: when will you make the switch?
Frequently Asked Questions
Everything you need to know
Most Web3 apps use outdated libraries like ethers.js that make excessive RPC calls. Modern apps using viem + wagmi reduce RPC requests by 75% through automatic multicall batching, intelligent caching, and request deduplication. A typical Web3 dashboard makes 50-100 RPC calls on load with old tech versus 10-25 with modern infrastructure.
Multicall batches multiple blockchain read operations into a single RPC call. Instead of making 10 separate requests (3 seconds total), multicall retrieves all data in one request (~400ms). Modern libraries like viem include automatic multicall support, while ethers.js requires manual implementation with significant boilerplate code.
For a medium-sized Web3 application, migration typically takes 4-5 weeks and costs $8,000-15,000 in development time. However, most projects see RPC cost savings of $400-800/month, resulting in a payback period of 10-18 months, plus improved user retention and conversion rates.
Yes, viem and wagmi are fully compatible with all Ethereum smart contracts and don't require any changes to your existing contracts. The migration only affects the frontend code that interacts with blockchain. You can migrate gradually, keeping ethers.js alongside viem during the transition period.
Track key metrics: Time to Interactive (target under 2 seconds), RPC calls per session (aim for 70-80% reduction), bundle size (expect 30-50% smaller), and cache hit rate (60-70% for repeat visitors). Business metrics include bounce rate, session duration, transaction completion rate, and monthly RPC costs.
Making redundant RPC calls without caching or batching. For example, fetching the same token balance separately for 5 different components instead of using a shared state management solution. Modern libraries like wagmi automatically deduplicate identical requests and cache results, eliminating this problem entirely.
Written by
Maksym Koval