Microservices dengan NestJS di 2026: Arsitektur, gRPC, dan Pertanyaan Wawancara
Panduan praktis arsitektur NestJS microservices dengan gRPC: service boundaries, transport layers, streaming patterns, dan pertanyaan wawancara umum untuk 2026.

Arsitektur microservices NestJS telah menjadi pendekatan standar untuk membangun backend Node.js terdistribusi pada tahun 2026. Dengan transport layer yang ditingkatkan pada NestJS 12, dukungan gRPC first-class, exception filters untuk RPC calls, dan propagasi trace ID otomatis, framework ini menyediakan semua yang diperlukan untuk memecah monolith menjadi services yang memiliki batas jelas tanpa mengorbankan developer experience.
gRPC menggunakan Protocol Buffers dan HTTP/2, memberikan serialisasi hingga 10x lebih cepat dan native bidirectional streaming dibandingkan JSON over REST. Untuk komunikasi service-to-service di dalam cluster, gRPC mengurangi latency dan memastikan kontrak yang ketat melalui file .proto. REST tetap menjadi pilihan yang lebih baik untuk public-facing APIs yang diakses oleh browser dan pihak ketiga.
Arsitektur Transport Layer NestJS Microservices
Package @nestjs/microservices menggantikan HTTP controllers dengan message-oriented handlers. Alih-alih routing berdasarkan URL path, setiap handler merespons message pattern, sebuah string atau object key yang mengidentifikasi operasi. Abstraksi ini berarti logic handler yang sama bekerja di TCP, Redis, NATS, Kafka, RabbitMQ, atau gRPC tanpa perubahan kode.
NestJS 11 memperkenalkan method unwrap() pada semua transporters, memberikan akses langsung ke underlying client instance. Ini menyelesaikan pain point lama: memeriksa connection state, tuning keepalive intervals, atau mengakses fitur spesifik broker yang tidak diekspos oleh abstraksi NestJS. NestJS 12 membangun di atas ini dengan pre-request hooks, memungkinkan handlers mengeksekusi logic kustom segera sebelum invokasi untuk cross-cutting concerns seperti auth checks atau metrics.
Dua pola komunikasi menggerakkan NestJS microservices:
- Request-response (
@MessagePattern): client mengirim message dan menunggu balasan. Cocok untuk synchronous queries seperti mengambil user profile atau memvalidasi token. - Event-based (
@EventPattern): client mengirimkan event dan melanjutkan, tidak ada response yang diharapkan. Ideal untuk audit logs, notifikasi, atau memicu 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: caller waits for the created order
@MessagePattern('order.create')
async createOrder(@Payload() data: CreateOrderDto) {
return this.ordersService.create(data);
}
// Event-based: fire and forget, no response returned
@EventPattern('order.shipped')
async handleOrderShipped(@Payload() data: { orderId: string }) {
await this.ordersService.markAsShipped(data.orderId);
}
}Handler @MessagePattern secara otomatis melakukan serialisasi return value dan mengirimkannya kembali melalui transport. Handler @EventPattern tidak mengembalikan apa pun: NestJS membuang return value apapun.
Mulai NestJS 12, transports TCP, Redis, NATS, MQTT, dan RabbitMQ mencatat deprecation warning ketika handler @EventPattern membalas ke ClientProxy#send(). Perilaku ini akan berubah di versi major berikutnya, selaras dengan pendekatan Kafka yang sudah ada. Migrasikan event handlers ke semantik fire-and-forget yang sebenarnya atau beralih ke @MessagePattern untuk flow request-response.
Konfigurasi gRPC sebagai Transport Microservice NestJS
Integrasi gRPC di NestJS dimulai dengan file .proto yang mendefinisikan service contract. Protocol Buffers memastikan type safety di level wire: baik client maupun server harus setuju dengan exact shape dari setiap message sebelum satu byte pun berjalan di network.
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;
}Di sisi server, aplikasi NestJS mem-bootstrap gRPC microservice dengan menunjuk ke proto file dan binding network address:
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();Controller menggunakan @GrpcMethod sebagai pengganti @MessagePattern. Decorator menerima nama service dan nama RPC method sebagai argumen, mapping langsung ke definisi proto:
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 menangani proto loading, serialisasi, dan HTTP/2 connection management secara otomatis. Method controller menerima plain TypeScript objects, tidak perlu decoding proto manual.
Pola Streaming gRPC dalam NestJS
Server streaming cocok untuk skenario di mana satu request menghasilkan multiple results seiring waktu: real-time price feeds, paginated database cursors, atau progress updates selama long-running task. Handler mengembalikan RxJS Observable, dan NestJS men-stream setiap emitted value ke client sebagai message gRPC terpisah:
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 users matching the filter one by one
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,
})),
);
}Bidirectional streaming menggunakan @GrpcStreamCall(). Baik client maupun server mengirim independent streams, berguna untuk sistem chat, collaborative editing, atau multiplexed telemetry ingestion. Handler menerima instance grpc.ServerDuplexStream dan mengelola read/write cycle secara manual.
NestJS 12 menambahkan backpressure handling: request streams sekarang pause saat replies mereka menunggu untuk ditulis. Ini mencegah buffer overflow ketika slow consumer tidak dapat mengikuti fast producer.
Observable yang crash di dalam gRPC stream mengakhiri seluruh call dengan status CANCELLED. Bungkus stream logic dalam operator catchError dan emit gRPC-appropriate error metadata. Unhandled stream errors adalah penyebab nomor satu dari mysterious connection drops di production NestJS gRPC services.
gRPC Exception Filters di NestJS 12
NestJS 12 memperkenalkan dedicated exception handling untuk gRPC, mencerminkan pola HTTP exception filter yang familiar. Status-specific exception classes memungkinkan handlers mengembalikan gRPC-native error codes alih-alih generic 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',
}));
}
}Terapkan filter secara global atau per-controller untuk memastikan respons error yang konsisten di semua gRPC endpoints. Dikombinasikan dengan class RpcException yang sudah ada, ini membawa paritas error handling antara HTTP dan gRPC transports.
Aplikasi Hybrid: HTTP dan gRPC pada Service yang Sama
Banyak real-world NestJS services membutuhkan baik public REST API maupun internal gRPC endpoints. Pola hybrid application menghubungkan multiple transports ke single NestJS instance:
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 on port 3000
const app = await NestFactory.create(AppModule);
// gRPC microservice on port 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();Pendekatan ini menghindari deployment services terpisah ketika single bounded context membutuhkan baik external maupun internal interfaces. Container dependency injection yang sama, guards, interceptors, dan pipes berlaku untuk kedua transports, mengurangi duplikasi dan menjaga perilaku tetap konsisten.
Siap menguasai wawancara Node.js / NestJS Anda?
Berlatih dengan simulator interaktif, flashcards, dan tes teknis kami.
Pola Regexp Kafka di NestJS 12
NestJS 12 memungkinkan @MessagePattern() dan @EventPattern() menerima regular expressions untuk Kafka topics. Satu handler sekarang dapat subscribe ke multiple topics secara dinamis:
import { Controller } from '@nestjs/common';
import { EventPattern, Payload, Ctx, KafkaContext } from '@nestjs/microservices';
@Controller()
export class AnalyticsController {
// Matches analytics.pageview, analytics.click, analytics.purchase, etc.
@EventPattern(/^analytics..*/)
handleAnalyticsEvent(
@Payload() data: Record<string, unknown>,
@Ctx() context: KafkaContext,
) {
const topic = context.getTopic();
console.log(`Received event on ${topic}`, data);
}
}Ini mengurangi boilerplate ketika multiple topics berbagi handler logic yang sama. Perhatikan bahwa validasi pattern key di NestJS 12 memastikan maksimum 256 karakter: patterns yang lebih panjang gagal secara diam-diam dan tidak cocok dengan handler manapun.
Migrasi NATS v3 di NestJS 12
NestJS 12 mengganti NATS client dengan package resmi @nats-io/transport-node. Ini adalah breaking change: deserializers sekarang menerima full message object alih-alih raw payload.
// Before (NestJS 11)
deserialize(value: any): any {
return JSON.parse(value);
}
// After (NestJS 12): read payload via msg.json()
deserialize(msg: any): any {
return msg.json();
}Update semua custom NATS deserializers saat migrasi ke NestJS 12. Client baru membawa improved performance dan alignment dengan official NATS ecosystem.
Batasan Service dan Domain-Driven Design dengan NestJS
Memecah monolith menjadi microservices tanpa batas yang jelas menciptakan distributed monolith, yang terburuk dari kedua arsitektur. Setiap NestJS microservice harus memiliki single bounded context: database sendiri, domain models sendiri, dan deployment lifecycle sendiri.
Panduan praktis untuk menggambar batasan service di NestJS:
- Satu modul NestJS per aggregate root. Jika
OrderdanOrderLineselalu berubah bersama, mereka termasuk dalam service yang sama. JikaUserdanOrderberubah secara independen, mereka layak memiliki services terpisah. - Async events untuk cross-domain side effects. Ketika order ditempatkan, emit event
order.createdvia Kafka atau RabbitMQ. Inventory service bereaksi tanpa order service mengetahui keberadaannya. - Shared proto packages untuk contracts. Simpan file
.protodi shared repository. Baik producer maupun consumer menghasilkan types dari source of truth yang sama, sehingga drift menjadi CI failure, bukan production incident.
Opsi microservice NestJS 12 dari DI container membuat konfigurasi service dapat diuji. Alih-alih hardcoding broker URLs di main.ts, inject ConfigService dan swap connection strings per environment tanpa rebuilding.
Pola Reliability: Timeouts, Retries, dan Circuit Breakers
Internal gRPC calls tanpa deadlines mengubah satu slow dependency menjadi system-wide outage. Setiap ClientProxy.send() call harus menyertakan timeout:
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-second deadline, 2 retries with 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 hanya boleh diterapkan pada idempotent operations. Retry call CreateOrder berisiko duplicate orders. Retry query FindOne aman karena tidak memiliki side effects.
Untuk fungsionalitas circuit breaker, library opossum terintegrasi dengan baik dengan NestJS. Bungkus ClientGrpc calls dalam circuit breaker yang terbuka setelah N consecutive failures dan tertutup setelah configurable reset timeout.
NestJS 12 melanjutkan automatic trace ID propagation yang diperkenalkan di NestJS 11 di seluruh Kafka, RabbitMQ, dan gRPC transports. Dikombinasikan dengan OpenTelemetry, ini memungkinkan full distributed tracing tanpa custom interceptors.
Pertanyaan Wawancara NestJS Microservices
Technical interviews untuk posisi backend semakin banyak menguji pengetahuan microservices bersamaan dengan framework-specific patterns. Pertanyaan-pertanyaan ini mencakup konsep yang paling sering ditanyakan dalam wawancara NestJS-focused.
Apa perbedaan antara @MessagePattern dan @EventPattern?
@MessagePattern mengimplementasikan request-response: client mengirim message dan blocks sampai menerima reply. @EventPattern mengimplementasikan fire-and-forget: client mengirim event dan melanjutkan eksekusi segera. Di bawah hood, @MessagePattern mengembalikan result handler melalui transport, sementara @EventPattern membuang return values. Perhatikan bahwa NestJS 12 mendeprecate replying dari @EventPattern handlers pada sebagian besar transports.
Bagaimana NestJS memuat dan mengikat file .proto untuk gRPC?
NestJS menggunakan package @grpc/proto-loader untuk mengurai file .proto saat startup dan menghasilkan service descriptors. Konfigurasi GrpcOptions menentukan proto path dan package name. Controllers yang dianotasi dengan @GrpcMethod('ServiceName', 'MethodName') dicocokkan dengan parsed descriptors. Jika method yang dideklarasikan di proto tidak memiliki matching handler, NestJS throws saat bootstrap.
Kapan gRPC harus menggantikan REST antar microservices?
gRPC cocok untuk internal service-to-service calls di mana type safety, performa, dan streaming penting. Protocol Buffers menghasilkan payloads yang lebih kecil dan serialisasi yang lebih cepat daripada JSON. HTTP/2 multiplexing mengurangi connection overhead. REST tetap lebih disukai untuk public APIs, browser clients, dan third-party integrations di mana human readability dan broad tooling support lebih penting daripada raw performance.
Bagaimana pola hybrid application bekerja?
NestFactory.create() mem-boot HTTP server. Memanggil app.connectMicroservice() menghubungkan additional transports (gRPC, Kafka, Redis, atau transporter yang didukung lainnya) ke instance aplikasi NestJS yang sama. Semua transports berbagi module tree, DI container, dan middleware pipeline yang sama. app.startAllMicroservices() memulai semua connected transporters, dan app.listen() memulai HTTP layer.
Pola reliability apa yang mencegah cascading failures?
Tiga pola yang paling penting: timeouts (setiap RPC call membutuhkan deadline), retries dengan jitter (hanya untuk idempotent operations, dengan exponential backoff plus random jitter untuk menghindari thundering herds), dan circuit breakers (terbuka setelah N failures, half-open setelah cooldown, tertutup begitu health checks lulus). Integrasi RxJS NestJS membuat timeouts dan retries dapat dikomposisikan melalui pipe operators.
Apa yang berubah untuk microservices di NestJS 12?
NestJS 12 menambahkan gRPC exception filters untuk status-specific error handling, Kafka regexp patterns untuk multi-topic handlers, dukungan NATS v3 dengan package client baru, pre-request hooks untuk microservice handlers, dan improved gRPC stream backpressure. Deprecation warning @EventPattern menandakan perubahan perilaku di masa depan di mana event handlers tidak lagi akan membalas ke send() calls.
Untuk latihan lebih mendalam tentang pola arsitektur NestJS, modul NestJS modules and dependency injection mencakup fundamental DI yang mendasari komposisi microservice. Modul middleware and interceptors membahas cross-cutting concerns yang dibagikan di seluruh transports. Panduan NestJS and GraphQL mencakup alternatif untuk gRPC untuk typed service APIs.
Mulai berlatih!
Uji pengetahuan Anda dengan simulator wawancara dan tes teknis kami.
Sources
- NestJS v12 is Now Available โ pengumuman resmi yang mencakup gRPC exception filters, Kafka regexp patterns, NATS v3, pre-request hooks
- NestJS Releases โ changelog termasuk gRPC stream backpressure, pattern key limits, EventPattern deprecation
- NestJS Hybrid Application Documentation โ panduan resmi untuk menggabungkan HTTP dan microservice transports
Poin Penting NestJS Microservices di 2026
- Abstraksi transport NestJS 12 memungkinkan services beralih antara TCP, gRPC, Kafka, dan NATS tanpa menulis ulang handler logic: decorator
@MessagePatterndan@EventPatternbekerja identik di semua transports - gRPC dengan Protocol Buffers memastikan kontrak yang ketat antar services melalui file
.proto, menangkap integration errors saat compile time bukan di production - Hybrid applications menggabungkan HTTP dan gRPC pada instance NestJS yang sama, menghilangkan kebutuhan untuk men-deploy services terpisah untuk public dan internal interfaces
- Server streaming via RxJS Observables memungkinkan real-time data feeds tanpa kompleksitas WebSocket, dengan NestJS 12 menambahkan backpressure handling untuk slow consumers
- Setiap internal RPC call membutuhkan deadline, retries hanya berlaku untuk idempotent operations, dan circuit breakers mencegah satu slow service dari cascading menjadi full outage
- Batasan service mengikuti domain-driven design: satu bounded context per service, async events untuk komunikasi cross-domain, shared proto packages untuk contract enforcement
Mulai berlatih!
Uji pengetahuan Anda dengan simulator wawancara dan tes teknis kami.
Bisakah kamu menemukan bug di Node.js / NestJS?
Satu potongan kode nyata, satu bug tersembunyi, satu percobaan per hari. Tanpa akun untuk mencoba.

Ditulis oleh
Anthony Fillion-MailletPendiri SharpSkill
Developer fullstack selama lebih dari 10 tahun. Ia menjalankan SharpSkill dan bertanggung jawab atas semua yang diterbitkan di sini.
Diperbarui 22 Oktober 2026
Tag
Bagikan
Artikel terkait

NestJS + Prisma: stack backend modern untuk Node.js
Panduan lengkap untuk membangun API backend modern dengan NestJS dan Prisma. Setup, model, service, transaksi, dan praktik terbaik dijelaskan.

NestJS: Membangun REST API Lengkap dari Nol
Panduan lengkap membangun REST API profesional dengan NestJS. Controller, Service, Module, validasi dengan class-validator, dan penanganan error dijelaskan secara praktis.

NestJS dan GraphQL di Tahun 2026: Schema, Resolver, dan Pertanyaan Interview
Panduan lengkap integrasi NestJS GraphQL dengan pendekatan schema-first dan code-first, pola resolver, serta pertanyaan interview untuk posisi senior developer.