๐ Subscription Management: WebSocket Lifecycle
Learn how to manage subscriptions, reconnect, and handle errors
Listen for smart contract events in real-time
Your Progress
0 / 5 completed๐๏ธ Managing Active Subscriptions
Subscriptions aren't fire-and-forget. They need lifecycle management: pause when app is backgrounded, resume on focus, unsubscribe on cleanup, reconnect on disconnection. Each subscription consumes a WebSocket connection slot (nodes limit you to ~10-50 concurrent subscriptions). Clean management = reliable app. Track subscription IDs, handle errors gracefully, and always unsubscribe when done. Leaked subscriptions waste resources and can get you rate-limited.
๐ฎ Interactive: Subscription Dashboard
Manage active subscriptions. Pause, resume, or unsubscribe to see how subscription lifecycle works in practice. Watch event counters update in real-time for active subscriptions.
USDC Transfers
activeUniswap Swaps
activeNFT Sales
pausedโป๏ธ Subscription Lifecycle
Send eth_subscribe with filters. Node responds with subscription ID (e.g., "0x1a2b3c..."). Store this IDโyou'll need it to unsubscribe.
Node pushes events via WebSocket: {subscription: "0x1a2b3c...", result: {...}}. Match incoming events to subscription ID to route correctly.
WebSocket can disconnect (network issue, node restart). Listen for close event, implement exponential backoff reconnection. Resubscribe with same filters after reconnect.
When done, send eth_unsubscribe with subscription ID. Critical in React: unsubscribe in cleanup function (useEffect return). Prevents memory leaks.
๐ป Code Example: React Hook
useEffect(() => {
const ws = new WebSocket('wss://mainnet.infura.io/ws/v3/...')
let subscriptionId: string | null = null
ws.onopen = () => {
// Subscribe to Transfer events on USDC
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'eth_subscribe',
params: ['logs', {
address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
topics: ['0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef']
}]
}))
}
ws.onmessage = (event) => {
const data = JSON.parse(event.data)
// Store subscription ID from initial response
if (data.id === 1) {
subscriptionId = data.result
console.log('Subscribed:', subscriptionId)
}
// Handle incoming events
if (data.params?.subscription === subscriptionId) {
console.log('New event:', data.params.result)
// Update UI, trigger notifications, etc.
}
}
// Cleanup: unsubscribe when component unmounts
return () => {
if (subscriptionId) {
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: 2,
method: 'eth_unsubscribe',
params: [subscriptionId]
}))
}
ws.close()
}
}, []) // Empty deps = subscribe once on mount, unsubscribe on unmount๐ก Key Insight
Always clean up subscriptions. In React/Vue/Angular, use framework lifecycle hooks (useEffect return, onUnmounted, ngOnDestroy) to unsubscribe. Forgetting this causes memory leaks: your app keeps receiving events for unmounted components, wasting CPU and memory. Nodes also track your subscriptionsโtoo many abandoned subscriptions get you rate-limited. The pattern: subscribe on mount, unsubscribe on unmount. Store subscription IDs in component state or a global map. When user navigates away or closes tab, send eth_unsubscribe for every active ID. This is non-negotiable for production apps. Clean lifecycle management = no leaks = happy users and happy RPC providers.