Backend & APIs2 min read557 words

Real-Time Applications with WebSockets in 2026: Complete Implementation Guide

Build real-time features with WebSockets. Learn connection management, scaling strategies, and implementation patterns for chat, collaboration, and live updates.

JL

Jishu Labs

Real-time features are expected in modern applications - from chat and notifications to collaborative editing. WebSockets provide the foundation for bidirectional communication. This guide covers production patterns for building scalable real-time systems.

WebSocket Server Setup

typescript
// WebSocket server with Socket.io
import { Server } from 'socket.io';
import { createAdapter } from '@socket.io/redis-adapter';
import { Redis } from 'ioredis';
import { verifyToken } from './auth';

const pubClient = new Redis(process.env.REDIS_URL!);
const subClient = pubClient.duplicate();

const io = new Server({
  cors: {
    origin: process.env.CLIENT_URL,
    credentials: true,
  },
  adapter: createAdapter(pubClient, subClient),
});

// Authentication middleware
io.use(async (socket, next) => {
  const token = socket.handshake.auth.token;
  
  if (!token) {
    return next(new Error('Authentication required'));
  }
  
  try {
    const user = await verifyToken(token);
    socket.data.user = user;
    next();
  } catch (error) {
    next(new Error('Invalid token'));
  }
});

// Connection handling
io.on('connection', (socket) => {
  const userId = socket.data.user.id;
  console.log(`User connected: ${userId}`);
  
  // Join user's personal room
  socket.join(`user:${userId}`);
  
  // Track online status
  pubClient.sadd('online-users', userId);
  io.emit('user:online', { userId });
  
  // Handle joining rooms
  socket.on('room:join', async (roomId: string) => {
    // Verify user has access to room
    const hasAccess = await checkRoomAccess(userId, roomId);
    if (!hasAccess) {
      socket.emit('error', { message: 'Access denied' });
      return;
    }
    
    socket.join(`room:${roomId}`);
    socket.to(`room:${roomId}`).emit('room:user-joined', {
      userId,
      roomId,
    });
  });
  
  // Handle messages
  socket.on('message:send', async (data) => {
    const message = await saveMessage({
      roomId: data.roomId,
      userId,
      content: data.content,
    });
    
    io.to(`room:${data.roomId}`).emit('message:new', message);
  });
  
  // Handle disconnection
  socket.on('disconnect', () => {
    pubClient.srem('online-users', userId);
    io.emit('user:offline', { userId });
  });
});

io.listen(3001);

Client Implementation

typescript
// React client with reconnection and state management
import { io, Socket } from 'socket.io-client';
import { create } from 'zustand';

interface SocketState {
  socket: Socket | null;
  connected: boolean;
  connect: (token: string) => void;
  disconnect: () => void;
}

export const useSocketStore = create<SocketState>((set, get) => ({
  socket: null,
  connected: false,
  
  connect: (token: string) => {
    const socket = io(process.env.NEXT_PUBLIC_WS_URL!, {
      auth: { token },
      reconnection: true,
      reconnectionAttempts: 5,
      reconnectionDelay: 1000,
      reconnectionDelayMax: 5000,
    });
    
    socket.on('connect', () => {
      console.log('Connected to WebSocket');
      set({ connected: true });
    });
    
    socket.on('disconnect', (reason) => {
      console.log('Disconnected:', reason);
      set({ connected: false });
    });
    
    socket.on('connect_error', (error) => {
      console.error('Connection error:', error.message);
    });
    
    set({ socket });
  },
  
  disconnect: () => {
    const { socket } = get();
    if (socket) {
      socket.disconnect();
      set({ socket: null, connected: false });
    }
  },
}));

// Custom hook for real-time messages
function useMessages(roomId: string) {
  const socket = useSocketStore((state) => state.socket);
  const [messages, setMessages] = useState<Message[]>([]);
  
  useEffect(() => {
    if (!socket) return;
    
    // Join room
    socket.emit('room:join', roomId);
    
    // Listen for messages
    socket.on('message:new', (message: Message) => {
      setMessages((prev) => [...prev, message]);
    });
    
    // Cleanup
    return () => {
      socket.off('message:new');
      socket.emit('room:leave', roomId);
    };
  }, [socket, roomId]);
  
  const sendMessage = useCallback((content: string) => {
    socket?.emit('message:send', { roomId, content });
  }, [socket, roomId]);
  
  return { messages, sendMessage };
}

Scaling Strategies

WebSocket Scaling Patterns

Horizontal Scaling:

- Use Redis adapter for multi-server pub/sub

- Implement sticky sessions or socket affinity

- Consider managed solutions (Pusher, Ably)

Performance:

- Use binary protocols (MessagePack) for large payloads

- Implement message batching for high-frequency updates

- Use room-based broadcasting instead of individual emissions

Reliability:

- Implement heartbeat/ping-pong for connection health

- Add message acknowledgments for critical events

- Use message queues for guaranteed delivery

Conclusion

WebSockets enable powerful real-time features when implemented correctly. Focus on proper authentication, connection management, and scaling patterns from the start.

Need help building real-time features? Contact Jishu Labs for expert backend development consulting.

References

  1. RFC 6455: The WebSocket ProtocolIETF
  2. The WebSocket APIMDN Web Docs
  3. Socket.IO documentationSocket.IO
JL

About Jishu Labs

Jishu Labs is a software development company founded in 2016. We build custom software, AI/ML systems, and full-stack web and mobile applications for clients, and we make eight AI tools for software teams.

Related Articles

Backend & APIs2 min read

What Is Database Normalization?

Normalization organises tables so each fact lives in exactly one place. Understanding what it prevents matters more than reciting the normal forms - and knowing when to break it matters most.

Jishu Labs

August 6, 2026

Backend & APIs3 min read

What Is an ER Diagram?

An entity-relationship diagram shows what things exist in a system and how they relate. Its real value is not documentation - it is that cardinality forces questions nobody asks until the data is wrong.

Jishu Labs

August 3, 2026

Backend & APIs3 min read

What Is a Schema Migration?

A migration is a versioned, repeatable change to a database structure. The interesting part is not writing them - it is running them against a live system without downtime or data loss.

Jishu Labs

July 29, 2026

Ready to Build Your Next Project?

Let's discuss how our expert team can help bring your vision to life.

AI Tools,
Built
End-to-End

Ready to Get Started?

Get consistent results. Collaborate in real-time.
Build Intelligent Apps. Work with Jishu Labs.

SCHEDULE MY CALL