Xây dựng kiến trúc Microservices với NestJS và Quản lý Monorepo bằng Nx
Hướng dẫn toàn diện về cách tổ chức, phát triển và chuẩn hóa hệ thống Microservices sử dụng NestJS kết hợp công cụ quản trị Monorepo thông minh Nx Dev Tools.

1. Giới thiệu tổng quan
Khi các ứng dụng web quy mô lớn phát triển, kiến trúc Monolith nguyên khối thường gặp phải các rào cản về việc mở rộng quy mô (scaling), thời gian triển khai (deployment pipeline) và tính phụ thuộc chéo giữa các module nghiệp vụ.
Kiến trúc Microservices xuất hiện nhằm giải quyết bài toán này bằng cách module hóa từng nghiệp vụ thành các dịch vụ độc lập. Khi triển khai Microservices trong hệ sinh thái Node.js/TypeScript, NestJS là framework hàng đầu nhờ cấu trúc module hóa chặt chẽ theo tư tưởng Dependency Injection (DI) và hỗ trợ đa giao thức kết nối (TCP, Redis, RabbitMQ, Kafka, gRPC).
Tuy nhiên, bài toán nảy sinh là: Làm thế nào để quản lý hàng chục repo riêng biệt mà vẫn tái sử dụng được mã nguồn (DTOs, Interfaces, Utilities, Guards)? Câu trả lời lý tưởng chính là Nx Monorepo.
2. Vì sao nên kết hợp NestJS và Nx?
Việc sử dụng đa repo (multi-repo) cho từng microservice thường dẫn đến tình trạng trôi phiên bản (version drift), khó đồng bộ các thư viện core và làm phức tạp hóa quy trình CI/CD. Kết hợp Nx vào NestJS mang lại các lợi thế chiến lược:
Tái sử dụng mã nguồn liền mạch (Shared Libraries): Các class DTO, schema database, helper format hay custom decorators chỉ cần viết một lần tại
libs/và được import trực tiếp vào tất cả microservices.Cơ chế Computation Caching thông minh: Nx ghi nhớ kết quả build, lint và test. Khi có commit mới, Nx chỉ build lại các service bị ảnh hưởng (Affected commands), giảm thiểu tới 70% thời gian CI/CD.
Project Graph tương tác: Cho phép hiển thị trực quan mối quan hệ phụ thuộc giữa các app và thư viện dùng chung chỉ bằng một câu lệnh
nx graph.Trải nghiệm Developer (DX) đồng nhất: Dễ dàng chạy đồng thời nhiều microservice local chỉ với một lệnh duy nhất.
3. Thiết kế cấu trúc thư mục Monorepo chuẩn
Một cấu trúc workspace Nx điển hình quản lý hệ thống thương mại điện tử với NestJS:
my-enterprise-workspace/
├── apps/
│ ├── api-gateway/ # Điểm đón request HTTP/REST từ client
│ ├── auth-service/ # Quản lý định danh, JWT, Passport
│ ├── product-service/ # Quản lý kho, danh mục, gRPC/Kafka consumer
│ └── order-service/ # Xử lý đơn hàng, thanh toán
├── libs/
│ ├── common/ # Global filters, interceptors, logger
│ ├── contracts/ # Event schemas, DTOs, Kafka topic constants
│ └── database/ # Prisma/TypeORM configs, base repositories
├── nx.json
├── package.json
└── tsconfig.base.json4. Các bước triển khai thực tế
Bước 1: Khởi tạo Workspace Nx
Khởi tạo một workspace trống hỗ trợ NestJS và TypeScript:
npx create-nx-workspace@latest enterprise-microservices --preset=nestBước 2: Tạo các Service độc lập
Sử dụng bộ generator của Nx để tạo Gateway và Service xử lý nghiệp vụ:
nx g @nx/nest:app apps/api-gateway
nx g @nx/nest:app apps/auth-service
nx g @nx/js:lib libs/contracts --publishable=falseBước 3: Định nghĩa Shared DTO trong libs/contracts
Trong thư viện dùng chung libs/contracts/src/lib/dtos/create-user.dto.ts:
import { IsEmail, IsString, MinLength } from 'class-validator';
export class CreateUserDto {
@IsEmail()
email: string;
@IsString()
@MinLength(6)
password: string;
}Cả
api-gatewayvàauth-servicecó thể trực tiếp import DTO này thông qua TypeScript path aliases (@enterprise/contracts) mà không cần đóng gói lên private npm registry.
Bước 4: Thiết lập giao tiếp Microservice qua Hybrid Application
Tại apps/auth-service/src/main.ts, cấu hình microservice lắng nghe qua TCP hoặc Message Broker:
import { NestFactory } from '@nestjs/core';
import { Transport, MicroserviceOptions } from '@nestjs/microservices';
import { AppModule } from './app/app.module';
async function bootstrap() {
const app = await NestFactory.createMicroservice<MicroserviceOptions>(AppModule, {
transport: Transport.TCP,
options: {
host: '127.0.0.1',
port: 8877,
},
});
await app.listen();
}
bootstrap();Tại apps/api-gateway, giao tiếp thông qua ClientsModule:
ClientsModule.register([
{
name: 'AUTH_SERVICE',
transport: Transport.TCP,
options: { host: '127.0.0.1', port: 8877 },
},
])5. Tối ưu hóa kiểm thử và triển khai với Nx Affected
Một trong những sức mạnh lớn nhất của Nx là khả năng phân tích sự thay đổi mã nguồn qua Git:
Kiểm tra các service chịu ảnh hưởng khi sửa đổi code tại
libs/contracts:
nx affected:appsBuild và Test chỉ những phần bị tác động:
nx affected -t test --parallel=3
nx affected -t build --configuration=production6. Bài học kinh nghiệm và Thực tiễn tốt nhất (Best Practices)
Giữ Shared Libraries ở trạng thái Stateless: Các thư viện trong
libs/chỉ nên chứa kiểu dữ liệu (contracts), constants và logic tiện ích thuần túy. Tránh đưa logic nghiệp vụ phụ thuộc chặt vào một database cụ thể vào common lib.Phân định rõ Boundary: Sử dụng cơ chế tags và module boundary linting của Nx (
@nx/enforce-module-boundaries) để ngăn chặn việcauth-serviceimport nhầm code củaproduct-service.Centralized Logging & Tracing: Khi hệ thống phân tán, nên tích hợp OpenTelemetry và một giải pháp tập trung log (như Winston + ELK hoặc Grafana Loki) ngay tại
libs/common.
Kiến trúc kết hợp NestJS và Nx mang lại sự cân bằng hoàn hảo giữa tính linh hoạt của Microservices và tính nhất quán, tinh gọn của Monorepo.