Logo
New RPC users get 35% off their first monthView the offer
OnFinality Learn
Network & Protocol Guides12 min read

Monad WebSocket RPC: WSS Endpoints, eth_subscribe, and Reliable Real-Time Streams

Learn how to connect to Monad's WebSocket RPC, use eth_subscribe for real-time data, and build resilient subscriptions with reconnection and resubscribe logic.

TL;DR

This guide explains how to use Monad's WebSocket RPC for real-time data streaming. It covers WSS endpoints, eth_subscribe subscription methods, notification payloads, and provides a runnable Node.js example with reconnection logic. It also includes troubleshooting tips for common issues like connection drops and high-volume subscriptions.

Direct Answer: How to Get Real-Time Data from Monad via WebSocket

To get real-time data from Monad, you connect to a WebSocket RPC endpoint (wss://) and use the standard Ethereum JSON-RPC eth_subscribe method to subscribe to events like new blocks, logs, and pending transactions. Monad is an EVM-compatible L1 with parallel execution and sub-second block times, so its WebSocket interface follows the Ethereum specification but with higher event frequency. This guide walks you through the endpoint surface, subscription methods, notification formats, and how to build a resilient client that handles reconnections and duplicate notifications.

Monad's official documentation provides a dedicated section on Execution Events and WebSocket Setup and a Real-Time Data Sources page, which are the primary references for this guide. For provider-specific endpoints and limits, always check your provider's documentation; we'll note where behavior is documented by Monad versus where it varies by provider.

  • Monad supports standard eth_subscribe methods: newHeads, logs, newPendingTransactions, and syncing.
  • Public endpoints may have connection limits and idle timeouts; use a provider with dedicated WebSocket support for production.
  • Monad's sub-second block times mean notifications arrive faster than on Ethereum, so design your client to handle high throughput.

Monad's WebSocket RPC Endpoint Surface

Monad exposes WebSocket RPC endpoints at wss:// URLs, similar to Ethereum. The exact endpoint depends on your node provider. For example, a public endpoint might be wss://rpc.monad.xyz (check Monad's docs for the current public endpoint), while providers like Chainstack, QuickNode, or Dwellir offer their own WSS URLs. Always use the wss:// scheme for encrypted connections; plain ws:// is rarely supported on public endpoints.

Monad's documentation lists supported JSON-RPC methods and notes differences from Ethereum, such as block tags and limits. For WebSocket, the key methods are eth_subscribe and eth_unsubscribe. The subscription types are the same as Ethereum: newHeads, logs, newPendingTransactions, and syncing. Monad also provides a custom executionEvents subscription for real-time state tracking, as described in the Execution Events and WebSocket Setup page.

When choosing an endpoint, consider that public endpoints often have rate limits and may drop idle connections. For production, use a provider that offers dedicated WebSocket connections with higher limits. OnFinality's API service and RPC pricing pages provide details on managed endpoints.

  • Always use wss:// for secure WebSocket connections.
  • Check your provider's documentation for the exact WSS URL and any connection limits.
  • Monad's public endpoint may be suitable for testing but not for high-volume production use.

Understanding eth_subscribe and Notification Payloads

The eth_subscribe method sends a subscription request and receives a subscription ID. Notifications are then pushed as JSON-RPC responses with the method eth_subscription. The payload for newHeads includes the block header object, which contains fields like number, hash, parentHash, timestamp, and transactionsRoot. For logs, the payload includes the log object with address, topics, data, blockNumber, transactionHash, and logIndex.

Monad's sub-second block times mean newHeads notifications arrive much more frequently than on Ethereum (which has ~12-second blocks). This can be a challenge for clients that process every block, so consider filtering or batching. For logs, you can specify an address and topics filter to reduce the volume of notifications.

Here's an example of a newHeads notification payload:

{
  "jsonrpc": "2.0",
  "method": "eth_subscription",
  "params": {
    "subscription": "0x1234567890abcdef",
    "result": {
      "number": "0x1b4",
      "hash": "0x...",
      "parentHash": "0x...",
      "timestamp": "0x...",
      "transactionsRoot": "0x..."
    }
  }
}

For logs, the payload includes the log entry. You can subscribe to logs for a specific contract address and topics to filter relevant events.

  • newHeads sends a block header for each new block.
  • logs sends logs matching the filter criteria.
  • newPendingTransactions sends transaction hashes for pending transactions.
  • syncing sends sync status changes.

Runnable example: subscribing and reconnecting with ethers.js

Below is a complete, self-contained Node.js script using ethers.js to connect to a Monad WebSocket endpoint, subscribe to new heads and logs, and handle reconnections with resubscription. The script uses a simple reconnect loop that resubscribes to the same filters after a connection drop. It also demonstrates idempotent duplicate notification handling by tracking the last seen block number.

To run this, install ethers.js (npm install ethers) and set the MONAD_WSS_URL environment variable to your endpoint. The script logs every notification and demonstrates how to handle duplicate notifications by tracking the last seen block number.

Expected output: The script will log subscription IDs, then print new head notifications with block number and hash, and log notifications as they arrive. Duplicate notifications (e.g., after reconnection) are filtered by the lastBlockNumber check. To test, run the script and observe the console. You should see a new head notification every few seconds (Monad's block time is sub-second, so expect rapid notifications). If the connection drops, the script reconnects and resubscribes automatically.

  • The script uses provider.send to call eth_subscribe directly, which works with ethers.js v6.
  • Reconnection logic is simple: on 'disconnected', reconnect after a delay and resubscribe.
  • Duplicate notifications are handled by tracking the last block number for newHeads.
const { WebSocketProvider } = require('ethers');

const WSS_URL = process.env.MONAD_WSS_URL || 'wss://rpc.monad.xyz';

async function main() {
  let provider;
  let lastBlockNumber = 0;

  async function connect() {
    console.log('Connecting to', WSS_URL);
    provider = new WebSocketProvider(WSS_URL);

    provider.on('error', (err) => {
      console.error('WebSocket error:', err);
    });

    provider.on('disconnected', () => {
      console.log('Disconnected. Reconnecting in 5s...');
      setTimeout(connect, 5000);
    });

    // Subscribe to new heads
    const headSub = await provider.send('eth_subscribe', ['newHeads']);
    console.log('Subscribed to newHeads with id:', headSub);

    // Subscribe to logs (example: all logs, adjust filter as needed)
    const logSub = await provider.send('eth_subscribe', ['logs', {}]);
    console.log('Subscribed to logs with id:', logSub);

    // Handle notifications
    provider.on('message', (message) => {
      const parsed = JSON.parse(message);
      if (parsed.method === 'eth_subscription') {
        const { subscription, result } = parsed.params;
        if (subscription === headSub) {
          const blockNum = parseInt(result.number, 16);
          if (blockNum > lastBlockNumber) {
            lastBlockNumber = blockNum;
            console.log('New head:', result.number, result.hash);
          } else {
            console.log('Duplicate head notification ignored:', result.number);
          }
        } else if (subscription === logSub) {
          console.log('New log:', result.address, result.topics);
        }
      }
    });
  }

  await connect();
}

main().catch(console.error);

Common Failures and Troubleshooting Checklist

WebSocket connections to Monad can fail for several reasons. Here are common issues and how to fix them:

Subscription excess: Some providers limit the number of active subscriptions per connection. If you exceed the limit, you may get an error. Reduce the number of subscriptions or use multiple connections.

Per-IP connection limits: Public endpoints often limit connections per IP. If you hit the limit, you'll be disconnected. Use a provider with higher limits or rotate IPs.

Block head lag: If your client processes notifications slowly, it may fall behind the chain head. This is more likely on Monad due to fast block times. Optimize your processing or use a more powerful machine.

Idle timeouts: Many providers close idle connections after a period. Send a ping or keepalive message periodically to keep the connection alive.

Reconnection storms: If the endpoint is temporarily down, your client may reconnect too aggressively. Use exponential backoff with jitter.

Duplicate notifications: After reconnection, you may receive notifications for blocks you already processed. Use idempotent processing (e.g., track last processed block).

  • Check your provider's documentation for subscription and connection limits.
  • Implement a heartbeat (e.g., send a ping every 30 seconds) to prevent idle timeouts.
  • Use exponential backoff for reconnection attempts.
  • Design your event processing to be idempotent to handle duplicates.

Tradeoffs and Limitations of Monad WebSocket RPC

Monad's fast block times are a double-edged sword: they provide low-latency data but also increase the volume of notifications. This can strain clients and networks. Consider the following tradeoffs:

Throughput vs. cost: High-frequency subscriptions consume more bandwidth and may incur higher costs on managed providers. Use filters to reduce data volume.

Finality vs. head: Monad uses MonadBFT consensus with sub-second block times, but finality may lag behind the head. If you need finalized data, subscribe to newHeads and check for finality using block tags like finalized.

Parallel execution: Monad's parallel execution means transactions are included in blocks differently than Ethereum. This doesn't affect WebSocket subscriptions directly, but it may affect how you interpret logs and transaction receipts.

Provider-specific limits: Each provider has its own rate limits, connection limits, and pricing. Always review your provider's documentation. OnFinality's Monad RPC rate limits and 429s guide covers common rate limit issues.

Public endpoints are not for production: Public endpoints are often rate-limited and may be unreliable. For production, use a dedicated provider or run your own node.

  • Use log filters to reduce notification volume.
  • Consider subscribing to finalized blocks for critical applications.
  • Monitor your bandwidth and adjust subscription frequency.
  • For production, use a managed provider like OnFinality's API service.

Next Steps and Further Reading

Now that you understand Monad WebSocket RPC, you can build real-time applications with confidence. Here are some next steps:

Explore Monad's official documentation on Execution Events and WebSocket Setup for advanced subscription types like executionEvents.

Review OnFinality's Monad RPC endpoints for a list of available endpoints and their features.

Learn about Monad RPC timeouts and retries to handle network issues gracefully.

Understand Monad RPC rate limits and 429s to avoid hitting limits.

Check out the OnFinality Learn hub for more guides on Monad and other networks.

If you're building on Monad, consider using OnFinality's API service for reliable and scalable RPC access.

  • Test your WebSocket client with a public endpoint first, then move to a provider.
  • Implement robust error handling and reconnection logic.
  • Monitor your subscription health with metrics.

Never Worry about Infrastructure Again

OnFinality takes away the heavy lifting of DevOps so you can build smarter and faster.

Get Started