Skip to main content
Practice Problems

How to implement WebSocket Gateways in NestJS?

WebSocket Gateways in NestJS

NestJS provides first-class support for WebSocket communication through Gateways. Gateways are classes annotated with @WebSocketGateway() that handle real-time bidirectional communication.


Setup

bash
npm install @nestjs/websockets @nestjs/platform-socket.io socket.io

Basic Gateway

typescript
import { WebSocketGateway, WebSocketServer, SubscribeMessage, MessageBody, ConnectedSocket, OnGatewayConnection, OnGatewayDisconnect, } from '@nestjs/websockets'; import { Server, Socket } from 'socket.io'; @WebSocketGateway({ cors: { origin: '*' }, namespace: '/chat', }) export class ChatGateway implements OnGatewayConnection, OnGatewayDisconnect { @WebSocketServer() server: Server; handleConnection(client: Socket) { console.log('Client connected:', client.id); } handleDisconnect(client: Socket) { console.log('Client disconnected:', client.id); } @SubscribeMessage('message') handleMessage( @MessageBody() data: { room: string; text: string }, @ConnectedSocket() client: Socket, ) { // Broadcast to room this.server.to(data.room).emit('message', { user: client.id, text: data.text, timestamp: new Date(), }); } @SubscribeMessage('joinRoom') handleJoinRoom( @MessageBody() room: string, @ConnectedSocket() client: Socket, ) { client.join(room); this.server.to(room).emit('userJoined', { userId: client.id }); return { event: 'joinedRoom', data: room }; } }

Register in Module

typescript
@Module({ providers: [ChatGateway, ChatService], }) export class ChatModule {}

Gateway with Authentication

typescript
@WebSocketGateway() export class ChatGateway implements OnGatewayConnection { constructor(private readonly authService: AuthService) {} async handleConnection(client: Socket) { try { const token = client.handshake.auth.token; const user = await this.authService.verifyToken(token); client.data.user = user; console.log(`User ${user.name} connected`); } catch (err) { client.emit('error', { message: 'Authentication failed' }); client.disconnect(); } } @SubscribeMessage('message') handleMessage( @MessageBody() data: { text: string }, @ConnectedSocket() client: Socket, ) { const user = client.data.user; this.server.emit('message', { user: user.name, text: data.text, }); } }

Using Guards with WebSockets

typescript
@Injectable() export class WsAuthGuard implements CanActivate { canActivate(context: ExecutionContext): boolean { const client = context.switchToWs().getClient<Socket>(); const user = client.data.user; return !!user; } } @WebSocketGateway() export class ChatGateway { @UseGuards(WsAuthGuard) @SubscribeMessage('message') handleMessage(@MessageBody() data: any) { // Only authenticated users reach here } }

Emitting from Services

typescript
@Injectable() export class NotificationService { constructor( @Inject('CHAT_GATEWAY') private readonly chatGateway: ChatGateway, ) {} async notifyUser(userId: string, notification: any) { this.chatGateway.server .to(`user:${userId}`) .emit('notification', notification); } }

Lifecycle Hooks

HookWhen
OnGatewayInitAfter gateway is initialized
OnGatewayConnectionWhen client connects
OnGatewayDisconnectWhen client disconnects

Client Example

typescript
import { io } from 'socket.io-client'; const socket = io('http://localhost:3000/chat', { auth: { token: 'jwt-token-here' }, }); socket.emit('joinRoom', 'general'); socket.emit('message', { room: 'general', text: 'Hello!' }); socket.on('message', (data) => { console.log(`${data.user}: ${data.text}`); });

Tip: Use NestJS Gateways for structured WebSocket handling with dependency injection, Guards, Interceptors, and Pipes — all the same patterns you use in REST controllers.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.

Finished reading?
Practice Problems