Microservices ด้วย NestJS ปี 2026: สถาปัตยกรรม, gRPC และคำถามสัมภาษณ์
คู่มือปฏิบัติสำหรับสถาปัตยกรรม NestJS microservices ด้วย gRPC: service boundaries, transport layers, streaming patterns และคำถามสัมภาษณ์ที่พบบ่อยปี 2026

NestJS microservices ได้กลายเป็นแนวทางมาตรฐานสำหรับการสร้าง distributed Node.js backends ในปี 2026 ด้วย enhanced transporter layer ของ NestJS 12, การรองรับ gRPC แบบ first-class, exception filters สำหรับ RPC calls และ automatic trace ID propagation framework นี้มอบทุกสิ่งที่จำเป็นสำหรับการแยก monolith ออกเป็น services ที่มีขอบเขตชัดเจนโดยไม่สูญเสีย developer experience
gRPC ใช้ Protocol Buffers และ HTTP/2 ให้ serialization เร็วกว่าถึง 10 เท่าและ native bidirectional streaming เมื่อเทียบกับ JSON over REST สำหรับการสื่อสาร service-to-service ภายใน cluster gRPC ลด latency และบังคับใช้ contracts ที่เข้มงวดผ่านไฟล์ .proto REST ยังคงเป็นตัวเลือกที่ดีกว่าสำหรับ public-facing APIs ที่ใช้โดย browsers และบุคคลที่สาม
สถาปัตยกรรม Transport Layer ของ NestJS Microservices
Package @nestjs/microservices แทนที่ HTTP controllers ด้วย message-oriented handlers แทนที่จะ routing ตาม URL path แต่ละ handler ตอบสนองต่อ message pattern ซึ่งเป็น string หรือ object key ที่ระบุ operation abstraction นี้หมายความว่า handler logic เดียวกันทำงานข้าม TCP, Redis, NATS, Kafka, RabbitMQ หรือ gRPC โดยไม่ต้องเปลี่ยน code
NestJS 11 แนะนำ method unwrap() บน transporters ทั้งหมด ให้การเข้าถึงโดยตรงไปยัง underlying client instance สิ่งนี้แก้ปัญหาที่มีมานาน: การตรวจสอบ connection state, การปรับ keepalive intervals หรือการเข้าถึง features เฉพาะของ broker ที่ NestJS abstraction ไม่ expose NestJS 12 สร้างบนสิ่งนี้ด้วย pre-request hooks ช่วยให้ handlers execute custom logic ทันทีก่อน invocation สำหรับ cross-cutting concerns เช่น auth checks หรือ metrics
communication patterns สองแบบขับเคลื่อน NestJS microservices:
- Request-response (
@MessagePattern): client ส่ง message และรอ reply เหมาะสำหรับ synchronous queries เช่นการดึง user profile หรือการ validate token - Event-based (
@EventPattern): client emit event และดำเนินการต่อ ไม่คาดหวัง response เหมาะอย่างยิ่งสำหรับ audit logs, notifications หรือการ trigger 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 serialize return value โดยอัตโนมัติและส่งกลับผ่าน transport Handler @EventPattern ไม่ return อะไรเลย: NestJS ทิ้ง return value ใดๆ
เริ่มต้นจาก NestJS 12 transports TCP, Redis, NATS, MQTT และ RabbitMQ บันทึก deprecation warning เมื่อ @EventPattern handler ตอบกลับไปยัง ClientProxy#send() behavior นี้จะเปลี่ยนในเวอร์ชัน major ถัดไป สอดคล้องกับแนวทางที่มีอยู่ของ Kafka ย้าย event handlers ไปยัง semantics fire-and-forget ที่แท้จริงหรือเปลี่ยนไปใช้ @MessagePattern สำหรับ request-response flows
การกำหนดค่า gRPC เป็น Transport ของ NestJS Microservice
การรวม gRPC ใน NestJS เริ่มต้นด้วยไฟล์ .proto ที่กำหนด service contract Protocol Buffers บังคับ type safety ที่ระดับ wire: ทั้ง client และ server ต้องเห็นด้วยกับ exact shape ของทุก message ก่อนที่ byte เดียวจะเดินทางผ่าน 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;
}ฝั่ง server แอปพลิเคชัน NestJS bootstraps gRPC microservice โดยชี้ไปที่ proto file และ 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 ใช้ @GrpcMethod แทน @MessagePattern decorator รับชื่อ service และชื่อ RPC method เป็น arguments mapping ตรงกับ proto definition:
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 จัดการ proto loading, serialization และ HTTP/2 connection management โดยอัตโนมัติ controller method รับ plain TypeScript objects ไม่ต้อง decode proto ด้วยตนเอง
รูปแบบ gRPC Streaming ใน NestJS
Server streaming เหมาะสำหรับสถานการณ์ที่ request เดียวสร้าง multiple results ตามเวลา: real-time price feeds, paginated database cursors หรือ progress updates ระหว่าง long-running task handler return RxJS Observable และ NestJS streams แต่ละ emitted value ไปยัง client เป็น gRPC message แยกกัน:
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 ใช้ @GrpcStreamCall() ทั้ง client และ server ส่ง independent streams มีประโยชน์สำหรับ chat systems, collaborative editing หรือ multiplexed telemetry ingestion handler รับ grpc.ServerDuplexStream instance และจัดการ read/write cycle ด้วยตนเอง
NestJS 12 เพิ่ม backpressure handling: request streams ตอนนี้ pause ขณะที่ replies ของพวกเขารอที่จะ write สิ่งนี้ป้องกัน buffer overflow เมื่อ slow consumer ไม่สามารถตามทัน fast producer
Observable ที่ crash ภายใน gRPC stream ยุติ call ทั้งหมดด้วยสถานะ CANCELLED ครอบ stream logic ใน catchError operators และ emit gRPC-appropriate error metadata Unhandled stream errors เป็นสาเหตุอันดับหนึ่งของ mysterious connection drops ใน production NestJS gRPC services
gRPC Exception Filters ใน NestJS 12
NestJS 12 แนะนำ dedicated exception handling สำหรับ gRPC สะท้อน HTTP exception filter pattern ที่คุ้นเคย Status-specific exception classes ให้ handlers return gRPC-native error codes แทน 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',
}));
}
}ใช้ filter แบบ globally หรือ per-controller เพื่อให้แน่ใจว่า error responses สม่ำเสมอข้าม gRPC endpoints ทั้งหมด รวมกับ class RpcException ที่มีอยู่ สิ่งนี้นำ error handling parity ระหว่าง HTTP และ gRPC transports
Hybrid Applications: HTTP และ gRPC บน Service เดียวกัน
NestJS services ในโลกจริงหลายตัวต้องการทั้ง public REST API และ internal gRPC endpoints hybrid application pattern เชื่อมต่อ multiple transports กับ 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();วิธีนี้หลีกเลี่ยงการ deploy services แยกกันเมื่อ bounded context เดียวต้องการทั้ง external และ internal interfaces dependency injection container เดียวกัน, guards, interceptors และ pipes ใช้กับทั้ง transports ลด duplication และรักษา behavior ให้สอดคล้องกัน
พร้อมที่จะพิชิตการสัมภาษณ์ Node.js / NestJS แล้วหรือยังครับ?
ฝึกฝนด้วยตัวจำลองแบบโต้ตอบ, flashcards และแบบทดสอบเทคนิคครับ
Kafka Regexp Patterns ใน NestJS 12
NestJS 12 อนุญาตให้ @MessagePattern() และ @EventPattern() รับ regular expressions สำหรับ Kafka topics handler เดียวตอนนี้สามารถ subscribe ไปยัง multiple topics แบบ dynamic:
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);
}
}สิ่งนี้ลด boilerplate เมื่อ multiple topics แชร์ handler logic เดียวกัน โปรดทราบว่า pattern key validation ใน NestJS 12 บังคับใช้สูงสุด 256 ตัวอักษร: patterns ที่ยาวกว่าล้มเหลวแบบเงียบๆ และไม่ match กับ handlers ใดเลย
การ Migration NATS v3 ใน NestJS 12
NestJS 12 แทนที่ NATS client ด้วย official @nats-io/transport-node package นี่คือ breaking change: deserializers ตอนนี้รับ full message object แทน 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();
}อัปเดต custom NATS deserializers ทั้งหมดเมื่อ migrate ไปยัง NestJS 12 client ใหม่นำ improved performance และ alignment กับ official NATS ecosystem
ขอบเขต Service และ Domain-Driven Design กับ NestJS
การแยก monolith เป็น microservices โดยไม่มีขอบเขตที่ชัดเจนสร้าง distributed monolith ซึ่งเป็นสิ่งที่แย่ที่สุดของทั้งสองสถาปัตยกรรม NestJS microservice แต่ละตัวควรเป็นเจ้าของ bounded context เดียว: database ของตัวเอง, domain models ของตัวเอง และ deployment lifecycle ของตัวเอง
แนวทางปฏิบัติสำหรับการวาดขอบเขต service ใน NestJS:
- หนึ่ง NestJS module ต่อ aggregate root ถ้า
OrderและOrderLineเปลี่ยนแปลงด้วยกันเสมอ พวกเขาอยู่ใน service เดียวกัน ถ้าUserและOrderเปลี่ยนแปลงอย่างอิสระ พวกเขาสมควรได้รับ services แยกกัน - Async events สำหรับ cross-domain side effects เมื่อ order ถูกวาง emit
order.createdevent ผ่าน Kafka หรือ RabbitMQ inventory service react โดยที่ order service ไม่รู้ว่ามันมีอยู่ - Shared proto packages สำหรับ contracts เก็บไฟล์
.protoใน shared repository ทั้ง producer และ consumer generate types จาก source of truth เดียวกัน ดังนั้น drift กลายเป็น CI failure ไม่ใช่ production incident
microservice options จาก DI container ของ NestJS 12 ทำให้ service configuration สามารถ test ได้ แทนที่จะ hardcode broker URLs ใน main.ts inject ConfigService และ swap connection strings ต่อ environment โดยไม่ต้อง rebuild
รูปแบบ Reliability: Timeouts, Retries และ Circuit Breakers
Internal gRPC calls ที่ไม่มี deadlines เปลี่ยน slow dependency เดียวเป็น system-wide outage ทุก ClientProxy.send() call ควรมี 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 ควรใช้กับ idempotent operations เท่านั้น การ retry CreateOrder call เสี่ยงต่อ duplicate orders การ retry FindOne query ปลอดภัยเพราะไม่มี side effects
สำหรับ circuit breaker functionality ไลบรารี opossum รวมเข้ากับ NestJS ได้ดี ครอบ ClientGrpc calls ใน circuit breaker ที่เปิดหลังจาก N consecutive failures และปิดหลังจาก configurable reset timeout
NestJS 12 ดำเนินการ automatic trace ID propagation ที่แนะนำใน NestJS 11 ต่อไปข้าม Kafka, RabbitMQ และ gRPC transports รวมกับ OpenTelemetry สิ่งนี้เปิดใช้งาน full distributed tracing โดยไม่ต้องมี custom interceptors
คำถามสัมภาษณ์ NestJS Microservices
การสัมภาษณ์ทางเทคนิคสำหรับตำแหน่ง backend ทดสอบความรู้ microservices ควบคู่กับ framework-specific patterns มากขึ้น คำถามเหล่านี้ครอบคลุม concepts ที่ถูกถามบ่อยที่สุดในการสัมภาษณ์ที่เน้น NestJS
ความแตกต่างระหว่าง @MessagePattern และ @EventPattern คืออะไร?
@MessagePattern implement request-response: client ส่ง message และ blocks จนกว่าจะได้รับ reply @EventPattern implement fire-and-forget: client emit event และดำเนินการต่อทันที ภายใต้ hood @MessagePattern return result ของ handler ผ่าน transport ขณะที่ @EventPattern ทิ้ง return values โปรดทราบว่า NestJS 12 deprecate การ replying จาก @EventPattern handlers บน transports ส่วนใหญ่
NestJS โหลดและ bind ไฟล์ .proto สำหรับ gRPC อย่างไร?
NestJS ใช้ package @grpc/proto-loader เพื่อ parse ไฟล์ .proto ตอน startup และ generate service descriptors การกำหนดค่า GrpcOptions ระบุ proto path และ package name Controllers ที่ annotate ด้วย @GrpcMethod('ServiceName', 'MethodName') ถูก match กับ parsed descriptors ถ้า method ที่ประกาศใน proto ไม่มี matching handler NestJS throws ตอน bootstrap
เมื่อไหร่ควรใช้ gRPC แทน REST ระหว่าง microservices?
gRPC เหมาะกับ internal service-to-service calls ที่ type safety, performance และ streaming สำคัญ Protocol Buffers สร้าง payloads ที่เล็กกว่าและ serialization ที่เร็วกว่า JSON HTTP/2 multiplexing ลด connection overhead REST ยังคงเป็นที่นิยมสำหรับ public APIs, browser clients และ third-party integrations ที่ human readability และ broad tooling support มีน้ำหนักมากกว่า raw performance
hybrid application pattern ทำงานอย่างไร?
NestFactory.create() boots HTTP server การเรียก app.connectMicroservice() แนบ additional transports (gRPC, Kafka, Redis หรือ supported transporter ใดๆ) กับ NestJS application instance เดียวกัน transports ทั้งหมดแชร์ module tree, DI container และ middleware pipeline เดียวกัน app.startAllMicroservices() เริ่ม connected transporters ทั้งหมด และ app.listen() เริ่ม HTTP layer
reliability patterns ใดที่ป้องกัน cascading failures?
สาม patterns ที่สำคัญที่สุด: timeouts (ทุก RPC call ต้องมี deadline), retries with jitter (เฉพาะสำหรับ idempotent operations, ด้วย exponential backoff บวก random jitter เพื่อหลีกเลี่ยง thundering herds) และ circuit breakers (เปิดหลังจาก N failures, half-open หลังจาก cooldown, ปิดเมื่อ health checks ผ่าน) การรวม RxJS ของ NestJS ทำให้ timeouts และ retries composable ผ่าน pipe operators
อะไรเปลี่ยนไปสำหรับ microservices ใน NestJS 12?
NestJS 12 เพิ่ม gRPC exception filters สำหรับ status-specific error handling, Kafka regexp patterns สำหรับ multi-topic handlers, การรองรับ NATS v3 ด้วย client package ใหม่, pre-request hooks สำหรับ microservice handlers และ improved gRPC stream backpressure @EventPattern deprecation warning ส่งสัญญาณ behavioral change ในอนาคตที่ event handlers จะไม่ reply ไปยัง send() calls อีกต่อไป
สำหรับการฝึกฝนลึกซึ้งยิ่งขึ้นเกี่ยวกับ NestJS architecture patterns โมดูล NestJS modules and dependency injection ครอบคลุม DI fundamentals ที่อยู่ใต้ microservice composition โมดูล middleware and interceptors กล่าวถึง cross-cutting concerns ที่แชร์ข้าม transports คู่มือ NestJS and GraphQL ครอบคลุม alternative สำหรับ gRPC สำหรับ typed service APIs
เริ่มฝึกซ้อมเลย!
ทดสอบความรู้ของคุณด้วยตัวจำลองสัมภาษณ์และแบบทดสอบเทคนิคครับ
Sources
- NestJS v12 is Now Available — ประกาศอย่างเป็นทางการครอบคลุม gRPC exception filters, Kafka regexp patterns, NATS v3, pre-request hooks
- NestJS Releases — changelog รวมถึง gRPC stream backpressure, pattern key limits, EventPattern deprecation
- NestJS Hybrid Application Documentation — คู่มืออย่างเป็นทางการสำหรับการรวม HTTP และ microservice transports
ประเด็นสำคัญสำหรับ NestJS Microservices ปี 2026
- transport abstraction ของ NestJS 12 ให้ services สลับระหว่าง TCP, gRPC, Kafka และ NATS โดยไม่ต้องเขียน handler logic ใหม่: decorators
@MessagePatternและ@EventPatternทำงานเหมือนกันข้าม transports ทั้งหมด - gRPC กับ Protocol Buffers บังคับ strict contracts ระหว่าง services ผ่านไฟล์
.protoจับ integration errors ตอน compile time แทนที่จะใน production - Hybrid applications รวม HTTP และ gRPC บน NestJS instance เดียวกัน ขจัดความจำเป็นในการ deploy services แยกสำหรับ public และ internal interfaces
- Server streaming ผ่าน RxJS Observables เปิดใช้งาน real-time data feeds โดยไม่มี WebSocket complexity โดย NestJS 12 เพิ่ม backpressure handling สำหรับ slow consumers
- ทุก internal RPC call ต้องมี deadline, retries ใช้กับ idempotent operations เท่านั้น และ circuit breakers ป้องกัน slow service เดียวจากการ cascading เป็น full outage
- ขอบเขต service ติดตาม domain-driven design: หนึ่ง bounded context ต่อ service, async events สำหรับ cross-domain communication, shared proto packages สำหรับ contract enforcement
เริ่มฝึกซ้อมเลย!
ทดสอบความรู้ของคุณด้วยตัวจำลองสัมภาษณ์และแบบทดสอบเทคนิคครับ
คุณหาบั๊กใน Node.js / NestJS เจอไหม
โค้ดจริงหนึ่งชิ้น บั๊กที่ซ่อนอยู่หนึ่งจุด วันละหนึ่งครั้ง ลองได้โดยไม่ต้องมีบัญชี

เขียนโดย
Anthony Fillion-Mailletผู้ก่อตั้ง SharpSkill
เป็นนักพัฒนาฟูลสแตกมากว่า 10 ปี ดูแล SharpSkill และรับผิดชอบทุกสิ่งที่เผยแพร่ที่นี่
อัปเดตเมื่อ 22 ตุลาคม 2569
แท็ก
แชร์
บทความที่เกี่ยวข้อง

NestJS + Prisma: สแตกแบ็กเอนด์สมัยใหม่สำหรับ Node.js
คู่มือฉบับสมบูรณ์ในการสร้าง API แบ็กเอนด์สมัยใหม่ด้วย NestJS และ Prisma ครอบคลุมการตั้งค่า โมเดล เซอร์วิส ทรานแซกชัน และแนวปฏิบัติที่ดี

NestJS: สร้าง REST API ที่สมบูรณ์ตั้งแต่เริ่มต้น
คู่มือฉบับสมบูรณ์สำหรับการสร้าง REST API ระดับมืออาชีพด้วย NestJS ครอบคลุม Controller, Service, Module, การตรวจสอบข้อมูลด้วย class-validator และการจัดการข้อผิดพลาด

NestJS และ GraphQL ในปี 2026: Schema, Resolver และคำถามสัมภาษณ์
คู่มือครบถ้วนสำหรับการผสานรวม NestJS GraphQL ด้วยแนวทาง schema-first และ code-first, รูปแบบ resolver และคำถามสัมภาษณ์สำหรับตำแหน่ง senior developer