Home/Blockchain/Event Subscription Demo/Subscription Management
โ†
Previous Module
RPC Calls Visualizer

๐Ÿ“‹ Subscription Management: WebSocket Lifecycle

Learn how to manage subscriptions, reconnect, and handle errors

Listen for smart contract events in real-time

๐ŸŽ›๏ธ 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.

Active Subscriptions
2
of 3 total
Total Events Received
2,184
across all subscriptions
Connection Status
Connected
WebSocket healthy

USDC Transfers

active
ID: 0x1a
Contract: 0x1234...
Event: Transfer
Events received: 1,247

Uniswap Swaps

active
ID: 0x2b
Contract: 0x5678...
Event: Swap
Events received: 892

NFT Sales

paused
ID: 0x3c
Contract: 0xabcd...
Event: OrderFulfilled
Events received: 45

โ™ป๏ธ Subscription Lifecycle

1.
Subscribe

Send eth_subscribe with filters. Node responds with subscription ID (e.g., "0x1a2b3c..."). Store this IDโ€”you'll need it to unsubscribe.

2.
Receive Events

Node pushes events via WebSocket: {subscription: "0x1a2b3c...", result: {...}}. Match incoming events to subscription ID to route correctly.

3.
Handle Errors

WebSocket can disconnect (network issue, node restart). Listen for close event, implement exponential backoff reconnection. Resubscribe with same filters after reconnect.

4.
Unsubscribe

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.

โ† Event Filtering