Microservices met NestJS in 2026: Architectuur, gRPC en Sollicitatievragen
Een praktische gids voor NestJS microservices-architectuur met gRPC, inclusief servicegrenzen, transport layers, streaming patterns en veelgestelde sollicitatievragen voor 2026.

NestJS microservices zijn de standaardaanpak geworden voor het bouwen van gedistribueerde Node.js backends in 2026. Met de verbeterde transporter-laag van NestJS 12, eersteklas gRPC-ondersteuning, exception filters voor RPC-aanroepen en automatische trace-ID-propagatie biedt het framework alles wat nodig is om een monoliet op te splitsen in goed afgebakende services zonder de developer experience op te offeren.
gRPC gebruikt Protocol Buffers en HTTP/2, wat tot 10x snellere serialisatie en native bidirectionele streaming oplevert vergeleken met JSON over REST. Voor service-naar-service-communicatie binnen een cluster vermindert gRPC de latency en handhaaft strikte contracten via .proto-bestanden. REST blijft de betere keuze voor publieke API's die door browsers en externe partijen worden geconsumeerd.
NestJS Microservices Transport Layer Architectuur
Het @nestjs/microservices-pakket vervangt HTTP-controllers door message-gerichte handlers. In plaats van te routeren op URL-pad, reageert elke handler op een message pattern, een string of object key die de operatie identificeert. Deze abstractie betekent dat dezelfde handler-logica werkt over TCP, Redis, NATS, Kafka, RabbitMQ of gRPC zonder codewijzigingen.
NestJS 11 introduceerde de unwrap()-methode op alle transporters, die directe toegang geeft tot de onderliggende client-instantie. Dit lost een langdurig pijnpunt op: verbindingsstatus inspecteren, keepalive-intervallen afstemmen of toegang krijgen tot broker-specifieke functies die de NestJS-abstractie niet blootstelt. NestJS 12 bouwt hierop voort met pre-request hooks, waarmee handlers aangepaste logica kunnen uitvoeren direct voor de aanroep voor cross-cutting concerns zoals auth-checks of metrics.
Twee communicatiepatronen sturen NestJS microservices aan:
- Request-response (
@MessagePattern): de client stuurt een bericht en wacht op een antwoord. Geschikt voor synchrone queries zoals het ophalen van een gebruikersprofiel of het valideren van een token. - Event-based (
@EventPattern): de client verstuurt een event en gaat verder, geen antwoord verwacht. Ideaal voor audit logs, notificaties of het triggeren van downstream workflows.
import { Controller } from '@nestjs/common';
import { MessagePattern, EventPattern, Payload } from '@nestjs/microservices';
import { OrdersService } from './orders.service';
import { CreateOrderDto } from './dto/create-order.dto';
@Controller()
export class OrdersController {
constructor(private readonly ordersService: OrdersService) {}
// Request-response: aanroeper wacht op de aangemaakte order
@MessagePattern('order.create')
async createOrder(@Payload() data: CreateOrderDto) {
return this.ordersService.create(data);
}
// Event-based: fire and forget, geen antwoord
@EventPattern('order.shipped')
async handleOrderShipped(@Payload() data: { orderId: string }) {
await this.ordersService.markAsShipped(data.orderId);
}
}De @MessagePattern-handler serialiseert automatisch de returnwaarde en stuurt deze terug via het transport. De @EventPattern-handler retourneert niets: NestJS negeert elke returnwaarde.
Vanaf NestJS 12 loggen TCP-, Redis-, NATS-, MQTT- en RabbitMQ-transporters een deprecatiewaarschuwing wanneer een @EventPattern-handler antwoordt op ClientProxy#send(). Dit gedrag zal veranderen in de volgende major-versie, in lijn met de bestaande Kafka-aanpak. Migreer event handlers naar echte fire-and-forget-semantiek of schakel over naar @MessagePattern voor request-response flows.
gRPC Configureren als NestJS Microservice Transport
gRPC-integratie in NestJS begint met een .proto-bestand dat het servicecontract definieert. Protocol Buffers dwingen type safety af op wire-niveau: zowel client als server moeten het eens zijn over de exacte vorm van elk bericht voordat er een enkele byte over het netwerk gaat.
syntax = "proto3";
package users;
service UsersService {
rpc FindOne (UserById) returns (User);
rpc FindMany (UserFilter) returns (stream User);
}
message UserById {
string id = 1;
}
message UserFilter {
string role = 1;
int32 limit = 2;
}
message User {
string id = 1;
string email = 2;
string name = 3;
string role = 4;
}Aan de serverzijde bootstrapt de NestJS-applicatie een gRPC-microservice door te verwijzen naar het proto-bestand en een netwerkadres te binden:
import { NestFactory } from '@nestjs/core';
import { MicroserviceOptions, Transport } from '@nestjs/microservices';
import { join } from 'path';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.createMicroservice<MicroserviceOptions>(
AppModule,
{
transport: Transport.GRPC,
options: {
package: 'users',
protoPath: join(__dirname, 'proto/users.proto'),
url: '0.0.0.0:5000',
},
},
);
await app.listen();
}
bootstrap();De controller gebruikt @GrpcMethod in plaats van @MessagePattern. De decorator neemt de servicenaam en de RPC-methodenaam als argumenten, die direct mappen naar de proto-definitie:
import { Controller } from '@nestjs/common';
import { GrpcMethod } from '@nestjs/microservices';
import { UsersService } from './users.service';
@Controller()
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@GrpcMethod('UsersService', 'FindOne')
async findOne(data: { id: string }) {
return this.usersService.findById(data.id);
}
}NestJS regelt proto-loading, serialisatie en HTTP/2-verbindingsbeheer automatisch. De controller-methode ontvangt plain TypeScript-objecten, geen handmatige proto-decodering nodig.
gRPC Streaming Patterns in NestJS
Server streaming past bij scenario's waarin een enkel verzoek meerdere resultaten over tijd produceert: realtime prijsfeeds, gepagineerde database-cursors of voortgangsupdates tijdens een langlopende taak. De handler retourneert een RxJS Observable, en NestJS streamt elke geemitteerde waarde naar de client als een apart gRPC-bericht:
import { Observable, from } from 'rxjs';
import { map } from 'rxjs/operators';
import { GrpcMethod } from '@nestjs/microservices';
@GrpcMethod('UsersService', 'FindMany')
findMany(data: { role: string; limit: number }): Observable<any> {
// Stream gebruikers die aan de filter voldoen een voor een
const users$ = from(this.usersService.findByRole(data.role, data.limit));
return users$.pipe(
map((user) => ({
id: user.id,
email: user.email,
name: user.name,
role: user.role,
})),
);
}Bidirectionele streaming gebruikt @GrpcStreamCall(). Zowel client als server sturen onafhankelijke streams, nuttig voor chatsystemen, collaboratief bewerken of gemultiplexte telemetrie-ingestie. De handler ontvangt een grpc.ServerDuplexStream-instantie en beheert de read/write-cyclus handmatig.
NestJS 12 voegt backpressure-handling toe: request streams pauzeren nu terwijl hun antwoorden wachten om geschreven te worden. Dit voorkomt buffer overflow wanneer een langzame consumer een snelle producer niet kan bijhouden.
Een gecrashte Observable binnen een gRPC-stream beeindigt de hele aanroep met een CANCELLED-status. Wrap stream-logica in catchError-operators en emit gRPC-geschikte error metadata. Onbehandelde stream-fouten zijn de belangrijkste oorzaak van mysterieuze verbindingsonderbrekingen in productie NestJS gRPC-services.
gRPC Exception Filters in NestJS 12
NestJS 12 introduceert dedicated exception handling voor gRPC, gespiegeld aan het bekende HTTP exception filter pattern. Status-specifieke exception classes laten handlers gRPC-native foutcodes retourneren in plaats van generieke failures:
import { Catch, RpcExceptionFilter, ArgumentsHost } from '@nestjs/common';
import { Observable, throwError } from 'rxjs';
import { RpcException } from '@nestjs/microservices';
import { status } from '@grpc/grpc-js';
@Catch(RpcException)
export class GrpcExceptionFilter implements RpcExceptionFilter<RpcException> {
catch(exception: RpcException, host: ArgumentsHost): Observable<any> {
const error = exception.getError() as { code?: number; message?: string };
return throwError(() => ({
code: error.code ?? status.INTERNAL,
message: error.message ?? 'Internal error',
}));
}
}Pas de filter globaal of per controller toe om consistente error responses over alle gRPC-endpoints te garanderen. Gecombineerd met de bestaande RpcException-class brengt dit error handling pariteit tussen HTTP- en gRPC-transporten.
Hybride Applicaties: HTTP en gRPC op Dezelfde Service
Veel real-world NestJS-services hebben zowel een publieke REST API als interne gRPC-endpoints nodig. Het hybrid application pattern verbindt meerdere transporten met een enkele NestJS-instantie:
import { NestFactory } from '@nestjs/core';
import { MicroserviceOptions, Transport } from '@nestjs/microservices';
import { join } from 'path';
import { AppModule } from './app.module';
async function bootstrap() {
// HTTP-server op poort 3000
const app = await NestFactory.create(AppModule);
// gRPC-microservice op poort 5000
app.connectMicroservice<MicroserviceOptions>({
transport: Transport.GRPC,
options: {
package: 'users',
protoPath: join(__dirname, 'proto/users.proto'),
url: '0.0.0.0:5000',
},
});
await app.startAllMicroservices();
await app.listen(3000);
}
bootstrap();Deze aanpak vermijdt het deployen van aparte services wanneer een enkele bounded context zowel externe als interne interfaces nodig heeft. Dezelfde dependency injection container, guards, interceptors en pipes gelden voor beide transporten, wat duplicatie vermindert en gedrag consistent houdt.
Klaar om je Node.js / NestJS gesprekken te halen?
Oefen met onze interactieve simulatoren, flashcards en technische tests.
Kafka Regexp Patterns in NestJS 12
NestJS 12 staat toe dat @MessagePattern() en @EventPattern() reguliere expressies accepteren voor Kafka-topics. Een enkele handler kan nu dynamisch abonneren op meerdere topics:
import { Controller } from '@nestjs/common';
import { EventPattern, Payload, Ctx, KafkaContext } from '@nestjs/microservices';
@Controller()
export class AnalyticsController {
// Matcht analytics.pageview, analytics.click, analytics.purchase, etc.
@EventPattern(/^analytics..*/)
handleAnalyticsEvent(
@Payload() data: Record<string, unknown>,
@Ctx() context: KafkaContext,
) {
const topic = context.getTopic();
console.log(`Event ontvangen op ${topic}`, data);
}
}Dit vermindert boilerplate wanneer meerdere topics dezelfde handler-logica delen. De pattern key validatie in NestJS 12 handhaaft een maximum van 256 karakters: langere patterns falen stil en matchen geen handlers.
NATS v3 Migratie in NestJS 12
NestJS 12 vervangt de NATS-client door het officiele @nats-io/transport-node-pakket. Dit is een breaking change: deserializers ontvangen nu het volledige message-object in plaats van de raw payload.
// Voorheen (NestJS 11)
deserialize(value: any): any {
return JSON.parse(value);
}
// Daarna (NestJS 12): payload lezen via msg.json()
deserialize(msg: any): any {
return msg.json();
}Update alle custom NATS-deserializers bij de migratie naar NestJS 12. De nieuwe client brengt verbeterde performance en afstemming met het officiele NATS-ecosysteem.
Service Boundaries en Domain-Driven Design met NestJS
Een monoliet opsplitsen in microservices zonder duidelijke grenzen creert een gedistribueerde monoliet, het slechtste van beide architecturen. Elke NestJS-microservice moet een enkele bounded context bezitten: zijn eigen database, zijn eigen domeinmodellen en zijn eigen deployment lifecycle.
Praktische richtlijnen voor het tekenen van servicegrenzen in NestJS:
- Een NestJS-module per aggregate root. Als
OrderenOrderLinealtijd samen veranderen, horen ze in dezelfde service. AlsUserenOrderonafhankelijk veranderen, verdienen ze aparte services. - Async events voor cross-domain side effects. Wanneer een order wordt geplaatst, emit een
order.created-event via Kafka of RabbitMQ. De inventory-service reageert zonder dat de order-service weet dat die bestaat. - Gedeelde proto-pakketten voor contracten. Bewaar
.proto-bestanden in een gedeelde repository. Zowel producer als consumer genereren types vanuit dezelfde source of truth, zodat drift een CI-fout wordt, geen productie-incident.
De microservice-opties van NestJS 12 vanuit de DI-container maken serviceconfiguratie testbaar. In plaats van broker-URL's te hardcoden in main.ts, injecteer een ConfigService en wissel connection strings per omgeving zonder te rebuilden.
Betrouwbaarheidspatronen: Timeouts, Retries en Circuit Breakers
Interne gRPC-aanroepen zonder deadlines veranderen een enkele trage dependency in een systeembrede storing. Elke ClientProxy.send()-aanroep moet een timeout bevatten:
import { Inject, Injectable } from '@nestjs/common';
import { ClientGrpc } from '@nestjs/microservices';
import { firstValueFrom, timeout, retry } from 'rxjs';
@Injectable()
export class OrdersService {
private usersService: any;
constructor(@Inject('USERS_PACKAGE') private client: ClientGrpc) {}
onModuleInit() {
this.usersService = this.client.getService('UsersService');
}
async getOrderWithUser(orderId: string, userId: string) {
// 3-seconden deadline, 2 retries met exponential backoff
const user = await firstValueFrom(
this.usersService.findOne({ id: userId }).pipe(
timeout(3000),
retry({ count: 2, delay: (err, retryCount) => {
const jitter = Math.random() * 100;
return new Promise(r => setTimeout(r, 1000 * retryCount + jitter));
}}),
),
);
return { orderId, user };
}
}Retries mogen alleen gelden voor idempotente operaties. Een CreateOrder-aanroep opnieuw proberen riskeert dubbele orders. Een FindOne-query opnieuw proberen is veilig omdat het geen side effects heeft.
Voor circuit breaker-functionaliteit integreert de opossum-bibliotheek goed met NestJS. Wrap ClientGrpc-aanroepen in een circuit breaker die opent na N opeenvolgende failures en sluit na een configureerbare reset timeout.
NestJS 12 zet de automatische trace-ID-propagatie voort die in NestJS 11 werd geintroduceerd over Kafka-, RabbitMQ- en gRPC-transporten. Gecombineerd met OpenTelemetry maakt dit volledige gedistribueerde tracing mogelijk zonder custom interceptors.
NestJS Microservices Sollicitatievragen
Technische interviews voor backend-posities testen steeds vaker microservices-kennis naast framework-specifieke patterns. Deze vragen behandelen de concepten die het vaakst gevraagd worden in NestJS-gerichte interviews.
Wat is het verschil tussen @MessagePattern en @EventPattern?
@MessagePattern implementeert request-response: de client stuurt een bericht en blokkeert tot het een antwoord ontvangt. @EventPattern implementeert fire-and-forget: de client emit een event en gaat direct door met de uitvoering. Onder de motorkap retourneert @MessagePattern het resultaat van de handler via het transport, terwijl @EventPattern returnwaarden negeert. Merk op dat NestJS 12 het antwoorden vanuit @EventPattern-handlers op de meeste transporten heeft gedeprecieerd.
Hoe laadt en bindt NestJS .proto-bestanden voor gRPC?
NestJS gebruikt het @grpc/proto-loader-pakket om .proto-bestanden te parsen bij opstarten en service descriptors te genereren. De GrpcOptions-configuratie specificeert het proto-pad en de pakketnaam. Controllers geannoteerd met @GrpcMethod('ServiceName', 'MethodName') worden gematcht tegen de geparsede descriptors. Als een methode gedeclareerd in de proto geen matching handler heeft, gooit NestJS een fout bij bootstrap.
Wanneer moet gRPC REST vervangen tussen microservices?
gRPC past bij interne service-naar-service-aanroepen waar type safety, performance en streaming belangrijk zijn. Protocol Buffers produceren kleinere payloads en snellere serialisatie dan JSON. HTTP/2-multiplexing vermindert connection overhead. REST blijft te verkiezen voor publieke API's, browser-clients en third-party integraties waar menselijke leesbaarheid en brede tooling-ondersteuning zwaarder wegen dan ruwe performance.
Hoe werkt het hybrid application pattern?
NestFactory.create() boot een HTTP-server. Het aanroepen van app.connectMicroservice() koppelt extra transporten (gRPC, Kafka, Redis of elke ondersteunde transporter) aan dezelfde NestJS-applicatie-instantie. Alle transporten delen dezelfde module tree, DI-container en middleware pipeline. app.startAllMicroservices() start alle verbonden transporters, en app.listen() start de HTTP-laag.
Welke betrouwbaarheidspatronen voorkomen cascading failures?
Drie patronen zijn het belangrijkst: timeouts (elke RPC-aanroep heeft een deadline nodig), retries met jitter (alleen voor idempotente operaties, met exponential backoff plus random jitter om thundering herds te vermijden), en circuit breakers (open na N failures, half-open na een cooldown, gesloten zodra health checks slagen). De RxJS-integratie van NestJS maakt timeouts en retries composeerbaar via pipe operators.
Wat is er veranderd voor microservices in NestJS 12?
NestJS 12 voegde gRPC exception filters toe voor status-specifieke error handling, Kafka regexp patterns voor multi-topic handlers, NATS v3-ondersteuning met een nieuw client-pakket, pre-request hooks voor microservice handlers en verbeterde gRPC stream backpressure. De @EventPattern-deprecatiewaarschuwing signaleert een toekomstige gedragswijziging waarbij event handlers niet langer zullen antwoorden op send()-aanroepen.
Voor diepere oefening met NestJS-architectuurpatronen behandelt de NestJS modules and dependency injection-module de DI-fundamenten die ten grondslag liggen aan microservice-compositie. De middleware and interceptors-module behandelt cross-cutting concerns gedeeld over transporten. De NestJS en GraphQL-gids behandelt een alternatief voor gRPC voor getypeerde service-API's.
Begin met oefenen!
Test je kennis met onze gespreksimulatoren en technische tests.
Bronnen
- NestJS v12 is Now Available — officiele aankondiging over gRPC exception filters, Kafka regexp patterns, NATS v3, pre-request hooks
- NestJS Releases — changelog inclusief gRPC stream backpressure, pattern key limits, EventPattern deprecation
- NestJS Hybrid Application Documentation — officiele gids voor het combineren van HTTP en microservice transporten
Belangrijkste Inzichten voor NestJS Microservices in 2026
- De transport-abstractie van NestJS 12 stelt services in staat te wisselen tussen TCP, gRPC, Kafka en NATS zonder handler-logica te herschrijven: de
@MessagePattern- en@EventPattern-decorators werken identiek over alle transporten - gRPC met Protocol Buffers handhaaft strikte contracten tussen services via
.proto-bestanden, waardoor integratie-fouten worden afgevangen tijdens compile time in plaats van in productie - Hybride applicaties combineren HTTP en gRPC op dezelfde NestJS-instantie, waardoor het niet nodig is aparte services te deployen voor publieke en interne interfaces
- Server streaming via RxJS Observables maakt realtime datafeeds mogelijk zonder WebSocket-complexiteit, waarbij NestJS 12 backpressure handling toevoegt voor trage consumers
- Elke interne RPC-aanroep vereist een deadline, retries gelden alleen voor idempotente operaties, en circuit breakers voorkomen dat een enkele trage service cascadeert naar een volledige storing
- Servicegrenzen volgen domain-driven design: een bounded context per service, async events voor cross-domain communicatie, gedeelde proto-pakketten voor contracthandhaving
Begin met oefenen!
Test je kennis met onze gespreksimulatoren en technische tests.
Zie jij de bug in Node.js / NestJS?
Een echt codefragment, een verborgen bug, één poging per dag. Zonder account uit te proberen.

Geschreven door
Anthony Fillion-MailletOprichter van SharpSkill
Al meer dan 10 jaar fullstack-ontwikkelaar. Hij leidt SharpSkill en staat in voor alles wat hier verschijnt.
Bijgewerkt op 22 oktober 2026
Tags
Delen
Gerelateerde artikelen

NestJS + Prisma: de moderne backend-stack voor Node.js
Volledige gids voor het bouwen van een moderne backend-API met NestJS en Prisma. Setup, modellen, services, transacties en best practices uitgelegd.

NestJS: Een complete REST API vanaf nul bouwen
Stap-voor-stap handleiding voor het bouwen van een productieklare REST API met NestJS, TypeScript, Prisma en class-validator. CRUD, validatie, foutafhandeling en interceptors.

NestJS-sollicitatiegesprek: Guards, Interceptors en modulaire architectuur
Veelgestelde vragen in technische NestJS-sollicitatiegesprekken over Guards, Interceptors en modulaire architectuur, met concrete TypeScript-codevoorbeelden en technische uitleg.