Real-time applications are everywhere — from chat apps to live dashboards and multiplayer games. NestJS, a powerful and progressive Node.js framework, provides first-class support for WebSockets, making it easy to create real-time experiences. In this article, we’ll explore how to use WebSockets in NestJS to build efficient, scalable, and maintainable real-time features.
NestJS is a TypeScript-based Node.js framework built on top of Express (or optionally Fastify). It combines elements of OOP (Object Oriented Programming), FP (Functional Programming), and FRP (Functional Reactive Programming). It’s especially popular for building scalable server-side applications with strong typing and modular architecture.
WebSockets provide a full-duplex communication channel over a single TCP connection. Unlike HTTP, which is request-response-based, WebSockets allow the server to push data to the client anytime — ideal for real-time features like:
Live chat
Notifications
Real-time feeds
Multiplayer games
Collaborative editing tools
NestJS comes with built-in support for WebSockets using the @nestjs/websockets
package. Make sure you install it:
npm install @nestjs/websockets @nestjs/platform-socket.io
A gateway is how NestJS handles WebSocket communication. You can create one with the Nest CLI or manually:
nest g gateway chat
This will generate a chat.gateway.ts
file. Here’s a simple example:
import {
WebSocketGateway,
SubscribeMessage,
MessageBody,
ConnectedSocket,
OnGatewayConnection,
OnGatewayDisconnect,
} from '@nestjs/websockets';
import { Socket } from 'socket.io';
@WebSocketGateway({
cors: true, // Enable CORS for frontend apps
})
export class ChatGateway implements OnGatewayConnection, OnGatewayDisconnect {
handleConnection(client: Socket) {
console.log(`Client connected: ${client.id}`);
}
handleDisconnect(client: Socket) {
console.log(`Client disconnected: ${client.id}`);
}
@SubscribeMessage('message')
handleMessage(
@MessageBody() data: { sender: string; message: string },
@ConnectedSocket() client: Socket,
): void {
console.log(`Message from ${data.sender}: ${data.message}`);
client.broadcast.emit('message', data); // Send message to all clients except sender
}
}
Use Socket.IO in your frontend to connect:
<script src="https://cdn.socket.io/4.5.1/socket.io.min.js"></script>
<script>
const socket = io('http://localhost:3000');
socket.on('connect', () => {
console.log('Connected to server');
});
socket.emit('message', {
sender: 'User1',
message: 'Hello from client!',
});
socket.on('message', (data) => {
console.log('New message:', data);
});
</script>
NestJS WebSockets also supports:
Rooms: Using socket.join('room-name')
to send targeted messages.
Authentication: Add guards for gateway security.
Custom Adapters: Use Redis for scalability across multiple server instances.
Example of using rooms:
@SubscribeMessage('joinRoom')
handleJoinRoom(
@MessageBody() room: string,
@ConnectedSocket() client: Socket,
) {
client.join(room);
}
@SubscribeMessage('sendToRoom')
handleSendToRoom(
@MessageBody() data: { room: string; message: string },
@ConnectedSocket() client: Socket,
) {
client.to(data.room).emit('message', data.message);
}
Consider implementing:
Token-based auth during connection (e.g., JWT in handshake headers)
Role-based access using guards
Rate limiting and message validation
Use tools like Socket.IO Debug (localStorage.debug = '*';
) to inspect traffic.
Add extensive logging to gateway methods.
Use Postman’s WebSocket support or browser dev tools for testing.
NestJS makes working with WebSockets incredibly smooth thanks to its decorators, DI system, and modular architecture. Whether you’re building a simple chat or a complex real-time dashboard, NestJS and Socket.IO provide a robust foundation.
Want me to turn this into a blog post, markdown file, or even include Redis/cluster setup for scaling?