
NestJS review
TypeScript framework for Node.js servers with modules, dependency injection and decorators, on Express, Fastify or node:http
Verdict
NestJS gives TypeScript teams a fixed structure of modules, providers and decorators, with official packages for OpenAPI, WebSockets, microservice transports, authentication and the common ORMs. The catch is the amount of decorator and module code it asks for, the ESM-only move in version 12, and a steady run of security advisories in the Fastify adapter and microservices package over the past year.
Best for
TypeScript teams building larger APIs or microservices that want one agreed structure
Not for
Small services where plain routing is enough, or teams that need Bun, Deno or edge runtimes
Pros
- Modules and dependency injection give every project the same layout
- Runs on Express, Fastify or plain node:http through adapters
- Official packages for OpenAPI, WebSockets, auth, TypeORM, Drizzle and Mongoose
- Built-in microservice transports for Kafka, NATS, RabbitMQ, gRPC and more
Cons
- Many security advisories in the last year, mostly Fastify middleware bypasses
- Version 12 is ESM-only, which complicates upgrades of CommonJS apps and Jest suites
- Leans on decorators and classes, which adds code compared with plain routing
“This is why I like NestJS's swagger integration”
Hacker News, Sep 2026“a 5:1 boilerplate-to-biz-logic ratio”
Hacker News, May 2026“every foot gun there is with NestJS specifically”
Hacker News, Jan 2026
Is NestJS right for your project?
Describe what you need and AI will check the fit against this review.
NestJS features and capabilities
Modules and dependency injection
Code is split into modules whose providers are injected by the framework, so large codebases keep one layout and services are easy to swap in tests.
Choice of HTTP layer
The same controllers run on Express, Fastify or the new node:http adapter, so a team can change the HTTP layer without rewriting routes.
OpenAPI from code
The official @nestjs/swagger module builds an OpenAPI document and Swagger UI from decorators, DTO classes or Zod and Valibot schemas.
Validation with classes or schemas
Request bodies, params and queries are checked by the built-in ValidationPipe with class-validator, or since version 12 by Standard Schema libraries such as Zod.
Microservice transports
Services can talk over TCP, Redis, NATS, MQTT, RabbitMQ, Kafka or gRPC with the same handler code, which suits teams splitting a monolith.
- TypeScript firstWritten in TypeScript or ships its own types, with typed routes or handlers
- Yes
- Request validationValidates bodies, params or queries against a schema, in the core or an official package
- YesValidationPipe with class-validator, or Standard Schema such as Zod
- OpenAPI docsGenerates an OpenAPI spec or Swagger UI from routes
- YesOfficial @nestjs/swagger module
- Beyond Node.jsOfficially runs on Bun, Deno or edge runtimes such as Cloudflare Workers
- NoNode.js only; Bun is supported as a package manager
- WebSocketsBuilt in or through an official plugin
- Yes@nestjs/websockets with socket.io or ws
- Project structureModules, dependency injection or a fixed layout, not only routing
- YesModules, providers and dependency injection
- Database layerAn official ORM, query builder or data layer
- PartlyOfficial modules for TypeORM, Drizzle, Sequelize and Mongoose; no ORM of its own
- AuthenticationAn official auth module, plugin or strategy system
- Yes@nestjs/authentication, plus @nestjs/passport and @nestjs/jwt
At a glance
- Type
- Progressive Node.js framework
- Stack
- TypeScript / Node.js 20.19+
- Databases
- PostgreSQL, MySQL, SQLite, SQL Server, MongoDB
Free vs paid editions
What you get when you self-host, and what needs a paid plan.
The framework and its official packages are MIT, and nothing in them needs a licence key. The Nest team sells Mau, a deployment service that provisions your app, databases and brokers on AWS from $12 a month plus your AWS bill, along with NestJS Observe for tracing, which is free up to 300,000 events a month, official courses and enterprise support.
Running NestJS
Running a Nest 12 app needs Node.js 20.19 or later, or 22.12 or later on the 22.x line, and the CLI generators need Node.js 22.22.3, 24.15 or 26.
New cloud server to ready
10 s
Memory in use at idle
106 MB of 4 GB
Reads per second
8,182
Writes per second
5,268
Startup
1.13 s
Version tested
12.3.2 · Oct 31, 2026
- The app is one TypeScript file compiled with tsc: a DTO class with class-validator decorators, a controller and a module. Install plus build took 10 seconds and 81 MB including the TypeScript compiler, with 104 packages.
- Nest 12 packages are ESM only, but the CommonJS build ran without changes on Node.js 24, which can require ES modules.
- TypeScript 7 needed "types": ["node"] in tsconfig.json before it would see process. The build still emitted JavaScript without it.
- ValidationPipe listed every invalid field, and NotFoundException gave a consistent JSON 404.
import "reflect-metadata";
import { Body, Controller, Get, HttpCode, Module, NotFoundException, Param, ParseIntPipe, Post, ValidationPipe } from "@nestjs/common";
import { NestFactory } from "@nestjs/core";
import { ArrayMaxSize, IsArray, IsNumber, IsOptional, IsString, Length, Min } from "class-validator";
class CreateItemDto {
@IsString() @Length(1, 100) name: string;
@IsNumber() @Min(0) price: number;
@IsOptional() @IsArray() @IsString({ each: true }) @ArrayMaxSize(10) tags?: string[];
}
// 100 items kept in memory, so the test measures the framework, not a database.
const items = new Map<number, object>();
for (let i = 1; i <= 100; i++) items.set(i, { id: i, name: `Item ${i}`, price: i * 1.5, tags: ["sample"] });
let nextId = 101;
@Controller()
class ItemsController {
@Get("health")
health() { return { status: "ok" }; }
@Get("items/:id")
get(@Param("id", ParseIntPipe) id: number) {
const item = items.get(id);
if (!item) throw new NotFoundException("Not found");
return item;
}
@Post("items")
@HttpCode(201)
create(@Body() body: CreateItemDto) {
const item = { id: nextId++, ...body };
items.set(item.id, item);
return item;
}
}
@Module({ controllers: [ItemsController] })
class AppModule {}
async function bootstrap() {
const app = await NestFactory.create(AppModule, { logger: ["error", "warn"] });
app.useGlobalPipes(new ValidationPipe({ whitelist: true, forbidNonWhitelisted: true }));
await app.listen(Number(process.env.PORT ?? 3000), "127.0.0.1");
}
bootstrap();{
"message": [
"name must be longer than or equal to 1 characters",
"price must not be less than 0"
],
"error": "Bad Request",
"statusCode": 400
}What you can do with NestJS
Backend for a large product team
Give several teams one module layout, dependency injection and testing setup so services look the same across the codebase.
Event-driven microservices
Build services that exchange messages over Kafka, RabbitMQ or NATS with the same controllers and guards as the HTTP API.
Documented public API
Publish an OpenAPI document and Swagger UI generated from the controllers and DTOs, so client SDKs stay in step with the code.