DEV Community

Vigilmon
Vigilmon

Posted on

How to Monitor Socket.io Applications with Vigilmon

Socket.io powers real-time features in chat apps, collaborative tools, live dashboards, and multiplayer games. Unlike traditional HTTP APIs, Socket.io connections are persistent—which makes monitoring them uniquely challenging. When your Socket.io server goes down, connections don't cleanly fail; they silently hang or throw confusing client-side errors.

This guide shows you how to monitor Socket.io applications with Vigilmon using HTTP health checks alongside your real-time infrastructure.

What Can Go Wrong with Socket.io?

Socket.io failures come in several forms:

  1. Server crash: The Node.js process dies; all connections drop immediately
  2. Memory leak: Server accumulates connections without releasing them; eventually OOMs
  3. Event loop blocking: Heavy computation blocks the event loop; connections queue up or time out
  4. Adapter failures: Redis adapter for Socket.io in cluster mode loses sync
  5. Nginx proxy issues: WebSocket upgrade headers misconfigured; connections fall back to polling
  6. Sticky sessions breaking: Load balancer routes WebSocket to wrong server in cluster

External monitoring catches the most critical failures: server crashes and connectivity issues.

The Core Monitoring Strategy

Since Vigilmon uses HTTP checks (not WebSocket), the strategy is:

  1. Add HTTP health endpoints to your Socket.io server
  2. Monitor the HTTP endpoints with Vigilmon
  3. Expose Socket.io metrics in the health response

This way, if your server is down or unhealthy, Vigilmon catches it within 60 seconds.

Adding Health Endpoints to a Socket.io Server

Express + Socket.io Setup

const express = require('express');
const http = require('http');
const { Server } = require('socket.io');

const app = express();
const server = http.createServer(app);
const io = new Server(server, {
  cors: { origin: '*' }
});

// Track connection state
let connectionCount = 0;
let totalConnectionsServed = 0;

io.on('connection', (socket) => {
  connectionCount++;
  totalConnectionsServed++;

  socket.on('disconnect', () => {
    connectionCount--;
  });
});

// Health check endpoint
app.get('/health', (req, res) => {
  const memUsage = process.memoryUsage();

  res.json({
    status: 'healthy',
    uptime: process.uptime(),
    activeConnections: connectionCount,
    totalServed: totalConnectionsServed,
    memory: {
      heapUsed: Math.round(memUsage.heapUsed / 1024 / 1024) + 'MB',
      heapTotal: Math.round(memUsage.heapTotal / 1024 / 1024) + 'MB',
    },
    timestamp: new Date().toISOString(),
  });
});

// Readiness check (is the server ready to accept connections?)
app.get('/ready', (req, res) => {
  // Check if Socket.io is initialized
  if (!io) {
    return res.status(503).json({ status: 'not ready' });
  }
  res.json({ status: 'ready' });
});

server.listen(3000);
Enter fullscreen mode Exit fullscreen mode

Checking Socket.io Engine Health

For more detailed Socket.io metrics:

app.get('/health/detailed', (req, res) => {
  const engine = io.engine;

  res.json({
    status: 'healthy',
    socketio: {
      activeConnections: connectionCount,
      engineConnections: engine ? engine.clientsCount : 0,
      pollingConnections: engine ? 
        Object.values(engine.clients).filter(c => c.transport.name === 'polling').length : 0,
      websocketConnections: engine ?
        Object.values(engine.clients).filter(c => c.transport.name === 'websocket').length : 0,
    },
    server: {
      uptime: Math.round(process.uptime()),
      memoryMB: Math.round(process.memoryUsage().heapUsed / 1024 / 1024),
      nodeVersion: process.version,
    },
    timestamp: new Date().toISOString(),
  });
});
Enter fullscreen mode Exit fullscreen mode

Adding Connection Alerts

Set up automatic alerts if connection count drops unexpectedly:

// Alert if connections drop from a high baseline
let maxConnectionsSeen = 0;
const CONNECTION_DROP_THRESHOLD = 0.5; // Alert if 50% drop in 5 minutes

setInterval(() => {
  if (connectionCount > maxConnectionsSeen) {
    maxConnectionsSeen = connectionCount;
  }

  if (maxConnectionsSeen > 10 && connectionCount < maxConnectionsSeen * CONNECTION_DROP_THRESHOLD) {
    console.error(`ALERT: Connection drop detected. Was ${maxConnectionsSeen}, now ${connectionCount}`);
    // Send alert via your preferred method (Slack, PagerDuty, etc.)
  }
}, 5 * 60 * 1000);
Enter fullscreen mode Exit fullscreen mode

Monitoring Socket.io in Clusters (with Redis Adapter)

If you run Socket.io in a cluster with the Redis adapter, your health check should verify Redis connectivity:

const { createAdapter } = require('@socket.io/redis-adapter');
const { createClient } = require('redis');

const pubClient = createClient({ url: process.env.REDIS_URL });
const subClient = pubClient.duplicate();

let redisConnected = false;

pubClient.on('connect', () => { redisConnected = true; });
pubClient.on('error', () => { redisConnected = false; });

await Promise.all([pubClient.connect(), subClient.connect()]);
io.adapter(createAdapter(pubClient, subClient));

// Updated health check
app.get('/health', (req, res) => {
  if (!redisConnected) {
    return res.status(503).json({
      status: 'degraded',
      reason: 'Redis adapter disconnected',
      activeConnections: connectionCount,
    });
  }

  res.json({
    status: 'healthy',
    activeConnections: connectionCount,
    redis: 'connected',
    timestamp: new Date().toISOString(),
  });
});
Enter fullscreen mode Exit fullscreen mode

Setting Up Vigilmon for Socket.io

  1. Sign up at vigilmon.online — free, no credit card
  2. Create Monitor 1: Health Endpoint

    • URL: https://your-socketio-server.com/health
    • Method: GET
    • Expected status: 200
    • Keyword: "healthy"
    • Interval: 1 minute
  3. Create Monitor 2: Server Reachability

    • URL: https://your-socketio-server.com/
    • Method: GET
    • Expected status: 200 (or 404, if / returns 404 intentionally)
    • This checks basic server connectivity
  4. Create Monitor 3: WebSocket Upgrade Path (if you have a landing page)

    • URL: https://your-app.com/socket.io/
    • Method: GET

Nginx Configuration for Socket.io (Required for Monitoring)

If you use Nginx in front of Socket.io, ensure it passes health check requests properly:

upstream socketio_backend {
  ip_hash;  # Required for sticky sessions
  server 127.0.0.1:3000;
  server 127.0.0.1:3001;
}

server {
  listen 443 ssl;
  server_name your-app.com;

  # WebSocket support
  location /socket.io/ {
    proxy_pass http://socketio_backend;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
  }

  # Health check endpoint (no WebSocket needed)
  location /health {
    proxy_pass http://socketio_backend;
    proxy_set_header Host $host;
    # No WebSocket headers needed here
  }
}
Enter fullscreen mode Exit fullscreen mode

What to Monitor vs What to Accept

Issue Detectable by Vigilmon? Action
Server crash ✅ Yes Immediate alert
High latency ✅ Yes (response time) Warning threshold
Memory leak ✅ Partially (via health endpoint) Alert when heapUsed > threshold
Individual socket disconnect ❌ No Implement client-side retry
Redis adapter failure ✅ Yes (via health endpoint) Critical alert
WebSocket upgrade failure ⚠️ Partial Monitor polling fallback rate

Sample Alert Configuration

For a production Socket.io application:

Monitor: Socket.io Health
URL: https://api.yourapp.com/health
Interval: 1 minute
Alert after: 2 consecutive failures
Alert channels:
  - Email: oncall@yourcompany.com
  - Slack: #engineering-alerts
  - PagerDuty: Production (for P1 incidents)
Enter fullscreen mode Exit fullscreen mode

Get Started Free

Vigilmon gives you free uptime monitoring with:

  • HTTP health checks with keyword validation
  • Multi-region monitoring (US, EU, Asia)
  • 1-minute check intervals
  • Slack, email, and PagerDuty alerts
  • Public status page for your users

Get alerted when your Socket.io server goes down — before your users notice dropped connections.

Top comments (0)