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

Intermediate 45 min Apr 12, 2026 783 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

不想自己管理这些吗?

我们为依赖稳定运行时间的企业管理基础设施。全托管服务,配备一位熟悉您系统架构的固定联系人。

您将拥有一位了解您整体架构的固定联系人

Rotterdam 04:06 · 一条消息即可联系我们,无需填写工单表单