· nestjs / fastify / nodejs

NestJS vs Fastify — framework đầy đủ so với micro-framework

NestJS cho team TypeScript lớn cần cấu trúc rõ ràng; Fastify cho microservice và edge khi cold start và throughput là ưu tiên. Số liệu đằng sau mỗi lựa chọn.

Bởi

2.249 từ · 12 phút đọc

Nếu bạn đang xây dựng monolith với một team TypeScript đông người, hãy chọn NestJS. Nếu bạn đang xây dựng microservice low-latency hoặc deploy lên serverless edge, hãy chọn Fastify. Hai framework này giải quyết những bài toán khác nhau, và không cái nào là lựa chọn mặc định hợp lý cho use case của cái kia.

Bài này dành cho ai

Các backend developer Node.js đang chọn framework chính cho dự án mới — hoặc đang cân nhắc migrate từ Express. Nếu bạn đã đầu tư sâu vào NestJS với các pattern đã định hình, bài toán migration sẽ khác; hãy nhảy thẳng đến kết luận.

Dữ liệu chúng tôi dùng

Các con số trong bài đến từ hai bộ benchmark độc lập:

  • Fastify official benchmarks (tháng 1/2026): single-thread “hello world,” đo pure framework overhead.
  • drcodes.com (Node.js 20.11 LTS, Ubuntu 22.04, endpoint hello-world chuẩn): throughput, p99 latency, memory, và cold start trên Fastify, Express, và NestJS với Express adapter mặc định.

Dữ liệu multi-core và so sánh adapter: pkgpulse.com (tháng 3/2026, NestJS + Fastify adapter vs standalone Fastify).
Dữ liệu sát với thực tế production: leapcell.io (kịch bản có DB call, NestJS vs workload tương đương Express).


Tóm tắt nhanh

Tiêu chíNestJS (Express adapter)Fastify
Throughput (thuần)28.163 req/s76.835 req/s
Throughput (có DB call)~8.500 QPS~9.200 QPS (baseline Express)
p99 latency58ms18ms
Memory mỗi worker89MB45MB
Cold start340ms125ms
DXCó cấu trúc (DI, decorators, modules)Tối giản — tự chọn
Độ khó ban đầuDốc nếu không có nền DINhẹ — quen Express là dùng được
EcosystemPhong phú (Swagger, CQRS, auth, TypeORM)Tập trung (official plugins, Ajv)
Hỗ trợ enterpriseCó — Trilon commercial contractsOpenJS Foundation

Khoảng cách throughput thuần là có thật. Khoảng cách thực tế khi có DB call thu hẹp còn 8%. p99 latency và cold start vẫn giữ nguyên trong workload thực — những con số đó quan trọng với edge deployment.


NestJS làm tốt điều gì

Dependency injection hoạt động được ở quy mô lớn

NestJS mang đến DI theo kiểu Angular: providers, modules, và constructor injection qua TypeScript decorators. Trong thực tế, điều này có nghĩa là bạn có thể hoán đổi UserRepository sang mock khi test mà không phải monkey-patch globals.

@Injectable()
export class UsersService {
  constructor(private readonly usersRepo: UsersRepository) {}

  findOne(id: string) {
    return this.usersRepo.findById(id);
  }
}

Test trở nên gọn gàng:

const module = await Test.createTestingModule({
  providers: [
    UsersService,
    { provide: UsersRepository, useClass: MockUsersRepository },
  ],
}).compile();

Những developer quen với Spring Boot hoặc C# sẽ thấy module system này quen thuộc ngay. Pattern đó có thể scale đến 50 kỹ sư mà không cần họp để thống nhất convention — framework đã enforce convention rồi.

Pipes, guards, và interceptors

Request lifecycle của NestJS rõ ràng: guards cho auth, pipes cho validation, interceptors cho logging và transformation. Mỗi thứ đều có type, có thể test riêng lẻ, và được khai báo ngay tại chỗ nó chạy.

@UseGuards(JwtAuthGuard)
@UsePipes(new ValidationPipe({ transform: true }))
@Controller('users')
export class UsersController {}

Không có magic theo convention ở đây. Khai báo ở đâu thì chạy ở đó. Để debug request processing, bạn chỉ cần đọc decorators, không phải quét qua mảng middleware.

Tự động sinh Swagger

@nestjs/swagger đọc DTOs và controller decorators rồi xuất ra OpenAPI spec. Không cần file YAML, không lo spec bị lệch với implementation. Với các team ship API như một sản phẩm — internal platform team, B2B SaaS — chỉ riêng điều này đã đủ để biện minh cho overhead của framework.

@ApiProperty({ example: '[email protected]', format: 'email' })
email: string;

Annotation này tự chuyển vào spec được sinh ra. Không cần bước build thêm.

CQRS và event sourcing có sẵn

@nestjs/cqrs đi kèm command handler, query handler, và event bus. Bạn có thể model một domain phức tạp mà không phải tự wire các pattern này. Không phải team nào cũng cần. Nhưng những team cần thì sẽ biết ơn vì không phải xây từ đầu.

Những điểm đáng chú ý từ cộng đồng

Cold start mới là vấn đề serverless thực sự. 340ms so với 125ms của Fastify là chênh lệch 2,7×. Khi Lambda liên tục xử lý cold start, con số này ảnh hưởng đến p50 latency của request đầu tiên sau mỗi lần idle. Các team dùng NestJS giải quyết bằng provisioned concurrency (tốn thêm chi phí) hoặc chuyển sang Fastify adapter (xem kết luận).

class-validator có các CVE chưa xử lý. Nếu bạn dùng ValidationPipe với setup class-validator mặc định, hãy kiểm tra CVE trước khi ship. Dùng zod hoặc validation dựa trên Ajv sẽ tránh được vấn đề này hoàn toàn.

Vấn đề N+1 với TypeORM. TypeORM là ORM được khuyến nghị mặc định trong tài liệu NestJS. Khi eager-load relations không cẩn thận, nó sinh ra N+1 queries. Hãy dùng Prisma hoặc Drizzle thay thế — cả hai tích hợp tốt với NestJS, và query API của Prisma khiến việc vô tình tạo N+1 trở nên khó hơn về mặt cấu trúc. So sánh đầy đủ các lựa chọn: TypeScript ORM tốt nhất 2026.


Fastify làm tốt điều gì

Benchmark có thật — nhưng chỉ một phần

Benchmark chính thức của Fastify: 46.664 req/s vs 9.433 req/s của Express — gấp khoảng 5× trong hello-world single-thread tổng hợp. Bộ multi-run của drcodes.com đặt Fastify ở 76.835 req/s vs NestJS+Express adapter ở 28.163 req/s — chênh lệch 2,7×.

Trong ứng dụng thực tế có DB call (benchmark leapcell.io), NestJS đạt ~8.500 QPS so với bare Express ở ~9.200 QPS — chênh lệch 8%. Khoảng cách thuần biến mất. Hai con số sống sót trong workload thực: p99 latency (18ms vs 58ms)cold start (125ms vs 340ms). Với serverless function và các path nhạy cảm về latency, đó là những con số có ý nghĩa thực.

Ajv schema validation là tính năng hạng nhất

Fastify validate và serialize qua Ajv theo mặc định. Bạn khai báo schema trên route:

const schema = {
  body: {
    type: 'object',
    properties: {
      email: { type: 'string', format: 'email' },
    },
    required: ['email'],
  },
};

fastify.post('/users', { schema }, async (request, reply) => {
  // request.body đã được validate — input lỗi không bao giờ đến được đây
});

Ajv JIT-compile schema khi khởi động. Validation nhanh và rõ ràng. Schema là plain data — có thể chia sẻ với client SDK generator, serialize thành JSON Schema, test độc lập với HTTP layer.

Plugin system với phạm vi riêng biệt

Fastify plugin bọc scope. Một plugin đăng ký decorator trong fastify.register(plugin) không rò rỉ sang plugin anh em. Điều này buộc bạn tạo cấu trúc có thể compose mà không cần framework áp đặt modules.

async function authPlugin(fastify, options) {
  fastify.decorate('verifyToken', async (token) => {
    // verify logic
  });
}

fastify.register(authPlugin);

Khi Val Town migrate từ Express sang Fastify, họ đánh giá cao plugin ecosystem: mọi nhu cầu về rate-limiting và observability đều có official plugin chất lượng cao. Lý do chính họ nêu là enforce OpenAPI spec trong code (thay vì file YAML chết) và native async/await xuyên suốt — scoped plugin model giúp mọi thứ compose được mà không bị conflict.

Bộ nhớ nhỏ hơn

45MB mỗi worker so với 89MB của NestJS. Với nhiều container microservice chạy đồng thời, đó là chi phí infrastructure thực. Trong môi trường có giới hạn memory chặt (Lambda tier 128MB chẳng hạn), sự khác biệt giữa vừa và không vừa là thực tế, không phải lý thuyết.


Case study thực tế

Val Town (công ty có tên, nguồn chính): đã migrate public API từ Express sang Fastify vào tháng 7/2024. Lý do họ nêu là chất lượng ecosystem — mọi công cụ observability đều có official first-party plugin — và native async/await xuyên suốt. Raw throughput không phải yếu tố quyết định; theo lời họ, “web framework overhead không phải vấn đề với Express.” Layer tương thích @fastify/express cho phép họ migrate từng route mà không có downtime.

Team ẩn danh (johal.in, 2026): đã migrate 47 microservice Fastify sang NestJS trong Q1 2026. Báo cáo tốc độ phát triển API nhanh hơn 40,2%. Lợi ích đến từ DX và cấu trúc được enforce, không phải runtime performance. Công ty không nêu tên — hãy xem như dữ liệu định hướng, không phải kết luận dứt khoát.

Enterprise dùng NestJS: Autodesk chạy NestJS với hơn 1 tỷ request/ngày và uptime 99,99%; Adidas dùng trên 30+ vùng toàn cầu cho e-commerce microservice; Roche dùng cho pipeline dữ liệu y tế (TypeScript safety được nêu là yêu cầu compliance). Hỗ trợ enterprise thương mại của NestJS qua Trilon là điểm khác biệt với các ngành có quy định chặt và SLA contract.


Migrate từ Express

Sang Fastify: Cài @fastify/express và migrate từng route một. Migration của Val Town gần hoàn tất — tất cả trừ hai route — trước khi họ đăng blog. Các điểm ma sát chính: sự khác biệt trong Express middleware API, và pattern next(err) của Express cần chuyển thành throw error hoặc reply.send(error). Hãy dành khoảng hai ngày để hiểu lifecycle hook của Fastify trước khi đụng đến middleware phức tạp. Xem thêm benchmark và hướng dẫn migrate tập trung tại Fastify vs Express.

Sang NestJS: Adapter @nestjs/platform-express cho phép bạn đặt NestJS lên cấu trúc Express cũ, nhưng làm vậy thì mất đi lợi ích của DI. Migrate NestJS thực sự là viết lại controller và service thành module. Với một Express API 200 route, hãy dành từ hai đến bốn tuần cho một team nhỏ — không phải chuyện làm trong cuối tuần. Chi phí ban đầu là thật; lợi ích trả về là thời gian onboard nhanh hơn cho mỗi kỹ sư mới.


Kết luận theo use case

Monolith với team 5 người trở lên: NestJS. Module system, DI, và testing utility hoàn vốn sau khoảng 20 route. Cấu trúc được enforce ngăn sự phình to hỗn loạn vốn sẽ giết chết Express monolith về dài hạn.

Microservice hoặc serverless edge function: Fastify. Cold start 125ms vs 340ms là con số đáng kể trên Lambda dưới tải. Lợi thế throughput 2,7× giữ vững trong workload nặng về framework overhead — nhiều request nhỏ nhanh, ít DB. Plugin ecosystem phủ observability và auth mà không cần kéo cả framework vào.

Ở giữa — bạn muốn cấu trúc NestJS nhưng cold start là vấn đề: NestJS với Fastify adapter. Đổi platform trong main.ts:

import { NestFactory } from '@nestjs/core';
import {
  FastifyAdapter,
  NestFastifyApplication,
} from '@nestjs/platform-fastify';

const app = await NestFactory.create<NestFastifyApplication>(
  AppModule,
  new FastifyAdapter(),
);
await app.listen({ port: 3000, host: '0.0.0.0' });

pkgpulse.com (tháng 3/2026) đặt NestJS + Fastify adapter ở ~180K req/s trong cấu hình multi-core tối ưu so với ~230K của standalone Fastify. Bạn hi sinh khoảng 22% throughput trần của Fastify; bạn giữ nguyên toàn bộ module và DI system của NestJS. Với hầu hết team, đây là đánh đổi xứng đáng.

Dự án mới, team nhỏ hoặc solo, không có nền Spring/Angular: Fastify với @fastify/autoload. Không có DI để học. Bạn chọn ORM, autoload plugin và route, rồi ship. Module system của NestJS là gánh nặng nhận thức thực sự nếu bạn không có background khiến nó trở nên quen thuộc — hãy chuẩn bị một tuần bỡ ngỡ trước khi mọi thứ click.


Deploy cả hai

Railway hỗ trợ cả NestJS và Fastify với tính năng tự nhận diện Node.js. Push code; Railway tự build và deploy mà không cần YAML. Hướng dẫn deploy cho cả hai framework đều đề cập biến môi trường, health check, và persistent storage.


Lưu ý

  • Khoảng cách throughput thu hẹp còn 8% khi có DB call. Nếu API của bạn bị bottleneck bởi DB, hãy chọn theo DX và nền tảng của team, không phải theo benchmark.
  • Cold start 340ms của NestJS được đo với Express adapter mặc định. Chuyển sang Fastify adapter sẽ giảm con số này; mức giảm chính xác phụ thuộc vào số lượng module bạn load.
  • Case study team ẩn danh (tăng 40,2% tốc độ dev) là tự báo cáo, không nêu tên công ty, và không được kiểm soát. Hãy xem như bằng chứng định hướng.
  • Số liệu enterprise adoption cho Autodesk, Adidas, và Roche được trích từ leapcell.io, nguồn này không cung cấp citation gốc. Hãy xem như định hướng — các công ty này là người dùng NestJS đã được biết đến, nhưng số liệu cụ thể (hơn 1 tỷ request/ngày, 30+ vùng) chưa được xác minh tại nguồn.
  • Bài này có affiliate link (Railway, Prisma). Xem toàn bộ thông tin.

Tài liệu tham khảo

  1. Fastify official benchmarks — tháng 1/2026
  2. drcodes.com Node.js 20.11 benchmark
  3. leapcell.io realistic workload benchmark
  4. pkgpulse.com NestJS+Fastify adapter benchmark — tháng 3/2026
  5. Val Town Fastify migration — tháng 7/2024
  6. Anonymous NestJS migration — 2026
  7. OpenJS Foundation Fastify growth — tháng 9/2024
  8. NestJS GitHub — số liệu: tháng 5/2026
  9. Fastify GitHub — số liệu: tháng 5/2026