Real-Time Communication in NestJS with WebSockets
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.
🧠 What is NestJS?
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.
🔌 Why Use WebSockets?
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
🚀 Getting Started with WebSockets in NestJS
1. Install Required Packages
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
2. Create a Gateway
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
}
}
3. Client-Side Example
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>
⚙️ Advanced Features
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);
}
🔐 Securing WebSocket Communication
Consider implementing:
Token-based auth during connection (e.g., JWT in handshake headers)
Role-based access using guards
Rate limiting and message validation
🧪 Testing and Debugging
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.
🧩 Conclusion
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?