Implement Deno WebSocket real-time applications with clustering and production deployment

Intermediate 45 min Apr 12, 2026 782 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Build production-ready real-time WebSocket applications with Deno, implementing clustering for high availability, SSL termination, and comprehensive monitoring for scalable messaging systems.

Prerequisites

  • Root or sudo access
  • Domain name for SSL certificates
  • Basic understanding of WebSockets
  • Familiarity with systemd services

What this solves

Modern applications require real-time communication for features like live chat, notifications, and collaborative editing. Deno provides excellent WebSocket support with built-in TypeScript and modern APIs, but production deployment requires clustering, load balancing, and proper monitoring. This tutorial implements a complete production-ready WebSocket infrastructure with automatic reconnection, horizontal scaling, and enterprise-grade monitoring.

Prerequisites and system preparation

Update system packages

Start by updating your package manager to ensure you get the latest versions of dependencies.

sudo apt update && sudo apt upgrade -y
sudo apt install -y curl unzip systemd nginx certbot python3-certbot-nginx
sudo dnf update -y
sudo dnf install -y curl unzip systemd nginx certbot python3-certbot-nginx

Install Deno runtime

Download and install the latest Deno runtime with security permissions configured for production use.

curl -fsSL https://deno.land/install.sh | sh
echo 'export DENO_INSTALL="$HOME/.deno"' >> ~/.bashrc
echo 'export PATH="$DENO_INSTALL/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
deno --version

Create application directory structure

Set up the directory structure with proper ownership for the WebSocket application and clustering configuration.

sudo mkdir -p /opt/websocket-app/{src,config,logs,static}
sudo useradd --system --shell /bin/false --home /opt/websocket-app websocket
sudo chown -R websocket:websocket /opt/websocket-app
sudo chmod 755 /opt/websocket-app
sudo chmod 775 /opt/websocket-app/logs

Step-by-step WebSocket server implementation

Create the main WebSocket server

Implement a production-ready WebSocket server with connection management, room-based messaging, and clustering support.

import { serve } from "https://deno.land/std@0.208.0/http/server.ts";
import { serveFile } from "https://deno.land/std@0.208.0/http/file_server.ts";

interface Connection {
  socket: WebSocket;
  userId: string;
  rooms: Set

Create WebSocket client with reconnection

Build a robust client-side WebSocket implementation with automatic reconnection, exponential backoff, and connection state management.

class WebSocketClient {
  constructor(url, userId) {
    this.url = url;
    this.userId = userId;
    this.socket = null;
    this.reconnectAttempts = 0;
    this.maxReconnectAttempts = 10;
    this.reconnectDelay = 1000;
    this.maxReconnectDelay = 30000;
    this.isConnected = false;
    this.messageQueue = [];
    this.eventHandlers = new Map();
    
    this.connect();
  }
  
  connect() {
    if (this.socket && this.socket.readyState === WebSocket.OPEN) {
      return;
    }
    
    const wsUrl = `${this.url}?userId=${encodeURIComponent(this.userId)}`;
    console.log('Connecting to:', wsUrl);
    
    this.socket = new WebSocket(wsUrl);
    
    this.socket.addEventListener('open', (event) => {
      console.log('WebSocket connected');
      this.isConnected = true;
      this.reconnectAttempts = 0;
      this.reconnectDelay = 1000;
      
      // Send queued messages
      while (this.messageQueue.length > 0) {
        const message = this.messageQueue.shift();
        this.socket.send(JSON.stringify(message));
      }
      
      this.emit('connected', event);
    });
    
    this.socket.addEventListener('message', (event) => {
      try {
        const message = JSON.parse(event.data);
        this.handleMessage(message);
      } catch (error) {
        console.error('Failed to parse message:', error);
      }
    });
    
    this.socket.addEventListener('close', (event) => {
      console.log('WebSocket disconnected:', event.code, event.reason);
      this.isConnected = false;
      this.emit('disconnected', event);
      
      if (this.reconnectAttempts < this.maxReconnectAttempts) {
        this.scheduleReconnect();
      } else {
        console.error('Max reconnection attempts reached');
        this.emit('maxReconnectAttemptsReached');
      }
    });
    
    this.socket.addEventListener('error', (event) => {
      console.error('WebSocket error:', event);
      this.emit('error', event);
    });
  }
  
  scheduleReconnect() {
    this.reconnectAttempts++;
    const delay = Math.min(
      this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1),
      this.maxReconnectDelay
    );
    
    console.log(`Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`);
    
    setTimeout(() => {
      this.connect();
    }, delay);
  }
  
  handleMessage(message) {
    switch (message.type) {
      case 'ping':
        this.send({ type: 'pong', timestamp: Date.now() });
        break;
        
      case 'message':
        this.emit('message', message);
        break;
        
      default:
        this.emit(message.type, message);
        break;
    }
  }
  
  send(message) {
    if (this.isConnected && this.socket.readyState === WebSocket.OPEN) {
      this.socket.send(JSON.stringify(message));
    } else {
      this.messageQueue.push(message);
    }
  }
  
  joinRoom(room) {
    this.send({ type: 'join', room });
  }
  
  leaveRoom(room) {
    this.send({ type: 'leave', room });
  }
  
  sendMessage(room, data) {
    this.send({ type: 'message', room, data });
  }
  
  on(event, handler) {
    if (!this.eventHandlers.has(event)) {
      this.eventHandlers.set(event, []);
    }
    this.eventHandlers.get(event).push(handler);
  }
  
  off(event, handler) {
    if (this.eventHandlers.has(event)) {
      const handlers = this.eventHandlers.get(event);
      const index = handlers.indexOf(handler);
      if (index > -1) {
        handlers.splice(index, 1);
      }
    }
  }
  
  emit(event, data) {
    if (this.eventHandlers.has(event)) {
      this.eventHandlers.get(event).forEach(handler => {
        try {
          handler(data);
        } catch (error) {
          console.error('Event handler error:', error);
        }
      });
    }
  }
  
  disconnect() {
    if (this.socket) {
      this.socket.close();
    }
  }
  
  getConnectionState() {
    return {
      isConnected: this.isConnected,
      reconnectAttempts: this.reconnectAttempts,
      queuedMessages: this.messageQueue.length,
      readyState: this.socket ? this.socket.readyState : WebSocket.CLOSED
    };
  }
}

Create HTML client interface

Build a simple HTML interface to test the WebSocket functionality with multiple rooms and real-time messaging.




    
    
    
    


    <h1>WebSocket Real-time Chat</h1>
    
    <div class="user-controls">
        
        
        
    </div>
    
    <div class="status disconnected">Disconnected</div>
    
    <div class="container">
        <div class="chat-room">
            <h3>Room: General</h3>
            <div class="messages"></div>
            <div class="message-input">
                
                
            </div>
            <div>
                
                
            </div>
        </div>
        
        <div class="chat-room">
            <h3>Room: Tech</h3>
            <div class="messages"></div>
            <div class="message-input">
                
                
            </div>
            <div>
                
                
            </div>
        </div>
    </div>
    
    
    

Automated install script

Run this to automate the entire setup

इसे खुद मैनेज नहीं करना चाहते?

हम उन businesses के लिए infrastructure संभालते हैं जो uptime पर निर्भर हैं। Fully managed, एक fixed contact के साथ जो आपके setup को जानता है।

आपको एक निश्चित contact मिलता है जो आपके setup को जानता है

Rotterdam 04:06 · एक message में पहुंचें, कोई ticket form नहीं