NestJS e WebSocket nel 2026: Comunicazione Real-Time, Gateway e Domande da Colloquio
Padroneggiare i WebSocket in NestJS con pattern Gateway, integrazione Socket.IO, autenticazione, gestione errori e domande frequenti nei colloqui tecnici 2026.

I WebSocket di NestJS offrono un approccio strutturato alla comunicazione real-time utilizzando il pattern Gateway. A differenza delle implementazioni WebSocket pure, NestJS astrae la complessità attraverso i decorator e si integra perfettamente con il sistema di dependency injection.
Un WebSocket Gateway in NestJS è una classe decorata con @WebSocketGateway() che gestisce la comunicazione bidirezionale tra client e server. Supporta molteplici adapter (Socket.IO, ws) e si integra con Guard, Pipe e Interceptor di NestJS.
Configurazione di un WebSocket Gateway con Socket.IO
L'adapter predefinito in NestJS utilizza Socket.IO, che fornisce riconnessione automatica, supporto per le room e fallback su HTTP long-polling. L'installazione richiede il pacchetto specifico della piattaforma insieme al modulo core WebSockets.
# terminal
npm install @nestjs/websockets @nestjs/platform-socket.io socket.ioUn gateway base ascolta i messaggi in arrivo e può trasmettere risposte ai client connessi.
import {
WebSocketGateway,
WebSocketServer,
SubscribeMessage,
MessageBody,
ConnectedSocket,
} from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';
@WebSocketGateway({
cors: { origin: '*' }, // Configure CORS for browser clients
})
export class ChatGateway {
@WebSocketServer()
server: Server; // Access to the underlying Socket.IO server
@SubscribeMessage('message') // Listen for 'message' events
handleMessage(
@MessageBody() data: { text: string; room: string },
@ConnectedSocket() client: Socket,
): void {
// Broadcast to all clients in the room except sender
client.to(data.room).emit('message', {
text: data.text,
senderId: client.id,
timestamp: Date.now(),
});
}
}Il decorator @SubscribeMessage associa un metodo a un nome evento specifico. @MessageBody() estrae il payload, mentre @ConnectedSocket() fornisce accesso al socket del client per risposte mirate.
Hook del Ciclo di Vita per la Gestione delle Connessioni
I gateway NestJS implementano interfacce del ciclo di vita per gestire connessioni e disconnessioni dei client. Questi hook abilitano la pulizia delle risorse, il tracciamento della presenza e la validazione delle connessioni.
import {
WebSocketGateway,
OnGatewayConnection,
OnGatewayDisconnect,
OnGatewayInit,
} from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';
import { Logger } from '@nestjs/common';
@WebSocketGateway()
export class PresenceGateway
implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect
{
private readonly logger = new Logger(PresenceGateway.name);
private connectedUsers = new Map<string, { joinedAt: Date }>();
afterInit(server: Server): void {
// Called once when the gateway initializes
this.logger.log('WebSocket Gateway initialized');
}
handleConnection(client: Socket): void {
// Track new connections
this.connectedUsers.set(client.id, { joinedAt: new Date() });
this.logger.log(`Client connected: ${client.id}`);
}
handleDisconnect(client: Socket): void {
// Cleanup on disconnect
this.connectedUsers.delete(client.id);
this.logger.log(`Client disconnected: ${client.id}`);
}
}Le tre interfacce del ciclo di vita hanno scopi distinti: OnGatewayInit viene eseguito una volta all'avvio, OnGatewayConnection si attiva per ogni connessione client, e OnGatewayDisconnect gestisce la pulizia quando i client si disconnettono.
Autenticazione con WebSocket Guard
Le connessioni WebSocket richiedono la validazione dell'autenticazione prima di consentire l'accesso a eventi protetti. I Guard NestJS funzionano con i gateway, anche se il contesto di esecuzione differisce dalle richieste HTTP. La documentazione ufficiale NestJS WebSockets tratta l'integrazione dei guard in dettaglio.
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { WsException } from '@nestjs/websockets';
import { JwtService } from '@nestjs/jwt';
import { Socket } from 'socket.io';
@Injectable()
export class WsAuthGuard implements CanActivate {
constructor(private jwtService: JwtService) {}
canActivate(context: ExecutionContext): boolean {
const client: Socket = context.switchToWs().getClient();
// Extract token from handshake auth or query params
const token =
client.handshake.auth?.token ||
client.handshake.query?.token;
if (!token) {
throw new WsException('Missing authentication token');
}
try {
const payload = this.jwtService.verify(token as string);
// Attach user data to socket for later use
client.data.user = payload;
return true;
} catch {
throw new WsException('Invalid token');
}
}
}Il guard viene applicato alla classe gateway o ai singoli handler dei messaggi usando il decorator @UseGuards(). La classe WsException lancia errori che il client riceve attraverso l'evento error di Socket.IO.
import { UseGuards } from '@nestjs/common';
import { WebSocketGateway, SubscribeMessage } from '@nestjs/websockets';
import { WsAuthGuard } from './ws-auth.guard';
@WebSocketGateway()
@UseGuards(WsAuthGuard) // Protect all handlers in this gateway
export class SecureChatGateway {
@SubscribeMessage('privateMessage')
handlePrivateMessage(): void {
// Only authenticated clients reach this handler
}
}Per domande sull'autenticazione a livello di modulo, il modulo interview sull'autenticazione NestJS copre strategie JWT e gestione delle sessioni.
Pronto a superare i tuoi colloqui su Node.js / NestJS?
Pratica con i nostri simulatori interattivi, flashcards e test tecnici.
Pattern di Broadcasting Basato su Room
Le room di Socket.IO abilitano la consegna mirata dei messaggi a sottoinsiemi di client connessi. I casi d'uso comuni includono chat room, lobby di gioco e funzionalità di collaborazione live.
import {
WebSocketGateway,
SubscribeMessage,
ConnectedSocket,
MessageBody,
WebSocketServer,
} from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';
@WebSocketGateway()
export class RoomGateway {
@WebSocketServer()
server: Server;
@SubscribeMessage('joinRoom')
handleJoinRoom(
@MessageBody() roomId: string,
@ConnectedSocket() client: Socket,
): { event: string; data: string } {
// Add client to the specified room
client.join(roomId);
// Notify others in the room
client.to(roomId).emit('userJoined', { userId: client.id });
return { event: 'joinedRoom', data: roomId };
}
@SubscribeMessage('leaveRoom')
handleLeaveRoom(
@MessageBody() roomId: string,
@ConnectedSocket() client: Socket,
): void {
client.leave(roomId);
client.to(roomId).emit('userLeft', { userId: client.id });
}
@SubscribeMessage('roomBroadcast')
handleRoomBroadcast(
@MessageBody() payload: { roomId: string; message: string },
): void {
// Send to all clients in room, including sender
this.server.to(payload.roomId).emit('roomMessage', payload.message);
}
}La distinzione tra client.to(room).emit() e server.to(room).emit() è importante: il primo esclude il mittente, mentre il secondo include tutti i membri della room.
Gestione degli Errori con Exception Filter
Le eccezioni WebSocket richiedono filtri dedicati poiché i filtri delle eccezioni HTTP non si applicano ai contesti gateway. I filtri personalizzati catturano WsException e formattano le risposte di errore per i client.
import { Catch, ArgumentsHost, ExceptionFilter } from '@nestjs/common';
import { WsException } from '@nestjs/websockets';
import { Socket } from 'socket.io';
@Catch(WsException)
export class WsExceptionFilter implements ExceptionFilter {
catch(exception: WsException, host: ArgumentsHost): void {
const client: Socket = host.switchToWs().getClient();
const error = exception.getError();
// Send structured error to client
client.emit('error', {
type: 'WsException',
message: typeof error === 'string' ? error : error,
timestamp: new Date().toISOString(),
});
}
}I filtri vengono applicati a livello di gateway per una gestione coerente degli errori su tutti gli handler dei messaggi.
import { UseFilters } from '@nestjs/common';
import { WebSocketGateway } from '@nestjs/websockets';
import { WsExceptionFilter } from './ws-exception.filter';
@WebSocketGateway()
@UseFilters(WsExceptionFilter)
export class FilteredGateway {
// All handlers benefit from centralized error handling
}Questo pattern rispecchia la filosofia NestJS di decorator e filtri descritta nel modulo middleware e interceptor.
Scalabilità dei WebSocket con Redis Adapter
I deployment WebSocket su singolo server falliscono quando il load balancing distribuisce i client su più istanze. Il Redis adapter di Socket.IO sincronizza gli eventi tra le istanze attraverso un meccanismo pub/sub.
import { Module } from '@nestjs/common';
import { createAdapter } from '@socket.io/redis-adapter';
import { createClient } from 'redis';
import { ChatGateway } from './chat.gateway';
@Module({
providers: [
ChatGateway,
{
provide: 'REDIS_ADAPTER',
useFactory: async () => {
const pubClient = createClient({ url: process.env.REDIS_URL });
const subClient = pubClient.duplicate();
await Promise.all([pubClient.connect(), subClient.connect()]);
return createAdapter(pubClient, subClient);
},
},
],
})
export class AppModule {}Il gateway utilizza quindi l'adapter per la comunicazione tra istanze.
import {
WebSocketGateway,
WebSocketServer,
OnGatewayInit,
} from '@nestjs/websockets';
import { Inject } from '@nestjs/common';
import { Server } from 'socket.io';
import { Adapter } from 'socket.io-adapter';
@WebSocketGateway()
export class ScalableGateway implements OnGatewayInit {
@WebSocketServer()
server: Server;
constructor(@Inject('REDIS_ADAPTER') private redisAdapter: Adapter) {}
afterInit(): void {
// Attach Redis adapter for multi-instance support
this.server.adapter(this.redisAdapter as any);
}
}Con il Redis adapter, un messaggio emesso su un'istanza server raggiunge i client connessi a qualsiasi istanza nel cluster.
Domande Frequenti nei Colloqui su NestJS WebSocket
I colloqui tecnici spesso indagano la comprensione delle decisioni architetturali real-time e dei dettagli implementativi specifici di NestJS.
Come gestisce NestJS l'autenticazione WebSocket in modo diverso da HTTP?
Il middleware HTTP non viene eseguito per le connessioni WebSocket. L'autenticazione avviene durante la fase di handshake o attraverso Guard applicati al gateway. La validazione del token tipicamente avviene in handleConnection() o in un Guard personalizzato che legge da socket.handshake.auth.
Qual è la differenza tra la configurazione della porta di @WebSocketGateway() e la porta dell'applicazione principale?
Per impostazione predefinita, i WebSocket Gateway condividono la porta del server HTTP. Specificando una porta in @WebSocketGateway(3001) si crea un server WebSocket separato su quella porta. Le porte condivise semplificano il deployment ma richiedono routing basato sul path (/socket.io) quando si utilizzano reverse proxy.
Come si testano i WebSocket Gateway in NestJS?
Le utility di test NestJS supportano il test dei gateway attraverso Test.createTestingModule(). La libreria socket.io-client si connette al server di test. Gli hook del ciclo di vita e gli handler dei messaggi vengono testati emettendo eventi e verificando le risposte o gli effetti collaterali.
import { Test } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import { io, Socket } from 'socket.io-client';
import { ChatGateway } from './chat.gateway';
describe('ChatGateway', () => {
let app: INestApplication;
let client: Socket;
beforeAll(async () => {
const module = await Test.createTestingModule({
providers: [ChatGateway],
}).compile();
app = module.createNestApplication();
await app.listen(3000);
client = io('http://localhost:3000');
});
afterAll(async () => {
client.disconnect();
await app.close();
});
it('receives message acknowledgment', (done) => {
client.emit('message', { text: 'test', room: 'lobby' });
client.on('message', (data) => {
expect(data.text).toBe('test');
done();
});
});
});Quando si dovrebbe usare l'adapter ws invece di Socket.IO?
L'adapter della libreria ws (@nestjs/platform-ws) offre minor overhead per applicazioni che non necessitano delle funzionalità di Socket.IO come riconnessione automatica, room o trasporti fallback. I sistemi di trading ad alta frequenza e i server di gioco spesso preferiscono ws per la latenza ridotta.
Per concetti architetturali NestJS più ampi, l'articolo correlato su Guard, Interceptor e Architettura Modulare copre come questi pattern si integrano attraverso i contesti HTTP e WebSocket.
Conclusione
- I WebSocket Gateway si integrano con dependency injection, Guard e Filter di NestJS per pattern coerenti tra endpoint HTTP e real-time
- Gli hook del ciclo di vita (
OnGatewayConnection,OnGatewayDisconnect) gestiscono il tracciamento della presenza e la pulizia delle risorse - I flussi di autenticazione differiscono da HTTP; la validazione del token avviene durante l'handshake o attraverso Guard WebSocket dedicati
- Il broadcasting basato su room con Socket.IO abilita la messaggistica mirata senza gestire manualmente le liste di socket
- Il Redis adapter risolve la scalabilità orizzontale sincronizzando gli eventi tra più istanze server
- I filtri delle eccezioni richiedono implementazioni specifiche per WebSocket usando
WsExceptione filtri personalizzati
Inizia a praticare!
Metti alla prova le tue conoscenze con i nostri simulatori di colloquio e test tecnici.

Scritto da
Anthony Fillion-MailletSviluppatore fullstack, fondatore di SharpSkill
Sviluppatore fullstack da oltre 10 anni. Guida SharpSkill e risponde di tutto ciò che vi viene pubblicato.
Aggiornato il 10 agosto 2026
Condividi
Articoli correlati

NestJS e GraphQL nel 2026: Schema, Resolver e Domande per Colloqui
L'integrazione di NestJS con GraphQL consente lo sviluppo di API type-safe. Questo tutorial copre gli approcci code-first e schema-first, pattern di resolver e domande da colloquio per il 2026.

NestJS e TypeORM nel 2026: migrazioni, relazioni e domande da colloquio
Gestire un database relazionale in un progetto NestJS richiede strumenti solidi. Questa guida analizza configurazione TypeORM, migrazioni, relazioni e domande da colloquio.

Node.js 24 nel 2026: URLPattern, Permission Model e Domande per Colloqui Tecnici
Node.js 24 LTS introduce un Permission Model stabile, URLPattern globale, gestione esplicita delle risorse con using/await using e V8 13.6. Un approfondimento sulle funzionalità rilevanti per la produzione e i colloqui tecnici.