Bỏ qua tới nội dung
Quay lại bài viết

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.

29/08/2026, 12:50NestJSMicroservicesNxMonorepoTypeScriptBackend Architecture
Xây dựng kiến trúc Microservices với NestJS và Quản lý Monorepo bằng Nx

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.json

4. 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=nest

Bướ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=false

Bướ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-gatewayauth-service có 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:apps
  • Build và Test chỉ những phần bị tác động:

nx affected -t test --parallel=3
nx affected -t build --configuration=production

6. 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ệc auth-service import nhầm code của product-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.