nest-best-practices

Installation
SKILL.md

NestJS is a progressive Node.js framework for building efficient and scalable server-side applications. It uses TypeScript by default, supports both Express and Fastify, and provides an out-of-the-box application architecture inspired by Angular. NestJS combines elements of OOP, FP, and FRP, making it ideal for building enterprise-grade applications.

Skill based on NestJS documentation, updated 2026-03-28. Covers NestJS v11 with Express v5.

How to Use This Skill

When generating NestJS code, read the relevant reference files below for the specific topic. The references contain current API patterns, correct import paths, and production-ready examples.

Always apply the production best practices below — these are patterns that matter in production and are easy to miss without explicit guidance.

NestJS v11 Breaking Changes

Be aware of these when generating code for NestJS v11+:

Node.js v20+ Required

Node.js v16 and v18 are no longer supported. Always target Node.js v20+.

Express v5 Route Matching

NestJS v11 uses Express v5 by default. Route patterns have changed:

Express v4 (Old) Express v5 (New) Notes
@Get('users/*') @Get('users/*splat') Wildcards must be named
forRoutes('*') forRoutes('{*splat}') Braces make path optional (matches root)
? optional character Not supported Use braces {} instead
Regex in routes Not supported Regex characters no longer work

CacheModule Migration to Keyv

The CacheModule now uses Keyv adapters instead of cache-manager stores:

// OLD (pre-v11) — no longer works
CacheModule.register({ store: redisStore, host: 'localhost', port: 6379 });

// NEW (v11+) — uses @keyv/redis
import { KeyvRedis } from '@keyv/redis';
CacheModule.registerAsync({
  useFactory: async () => ({
    stores: [new KeyvRedis('redis://localhost:6379')],
  }),
});

Production Best Practices

Bootstrap & Application Setup

Configure ValidationPipe globally in main.ts — this is a security-critical step:

app.useGlobalPipes(new ValidationPipe({
  whitelist: true,           // strips unknown properties
  forbidNonWhitelisted: true, // rejects requests with unknown properties (400)
  transform: true,            // enables automatic type coercion for params
}));

Entity & Schema Discipline

  • Use explicit column lengths: @Column({ length: 255 }), not bare @Column()
  • Name tables explicitly: @Entity('books') to avoid surprises with naming conventions
  • Use @CreateDateColumn() and @UpdateDateColumn() for automatic timestamps
  • Use specialized validators like @IsISBN(), @IsEmail(), @IsUUID() — not just @IsString()
  • Align nullability between entity and DTO: if @Column({ nullable: true }), the DTO field should be @IsOptional()

DTO Patterns

  • Import PartialType from @nestjs/swagger (not @nestjs/mapped-types) when using Swagger — this preserves API documentation metadata on partial fields
  • Zod validation is now an officially supported alternative to class-validator — use ZodValidationPipe with z.infer<typeof schema> for schema-first validation with type inference

Guards & Auth

NestJS v11 documents two auth approaches:

  1. Native JWT (recommended for simpler cases): Use @nestjs/jwt directly with a custom CanActivate guard that calls JwtService.verifyAsync(). No Passport dependency needed.
  2. Passport-based (for complex strategies like OAuth2, SAML): Use @nestjs/passport with PassportStrategy. Now documented under "recipes" rather than primary auth docs.

Regardless of approach:

  • Guard ordering matters: @UseGuards(JwtAuthGuard, RolesGuard) — JWT guard must run first to populate request.user before RolesGuard reads it
  • Use Reflector.getAllAndOverride() (not just .get()) so roles can be set at both handler and class level with handler taking precedence
  • RolesGuard must throw ForbiddenException with a descriptive message when the user lacks the required role — do NOT just return false from canActivate(). The generic 403 provides no diagnostic value. Include context: throw new ForbiddenException(\Requires roles: ${requiredRoles.join(', ')}`)`
  • Never hardcode JWT secrets — use JwtModule.registerAsync() with ConfigService
  • Define a Role enum rather than raw strings for type safety
  • In JwtStrategy.validate() (or native guard), validate the presence of required payload fields (sub, username, roles) before returning the user object. Define a JwtPayload interface for type safety.

Error Messages

All thrown exceptions (ForbiddenException, UnauthorizedException, NotFoundException, etc.) should include descriptive messages that identify what was expected, what was found, and what action the consumer should take. Do not rely on framework default messages in production code.

Microservices & Queues

  • For hybrid apps (HTTP + microservice), use NestFactory.create() + app.connectMicroservice() pattern
  • Always call app.enableShutdownHooks() when using Terminus health checks for graceful shutdown
  • Use @nestjs/bullmq (not @nestjs/bull) — it wraps the newer bullmq library. Config uses connection key (not redis):
    BullModule.forRoot({ connection: { host: 'localhost', port: 6379 } })
    
  • Use BullModule.forRootAsync() with ConfigService injection for production config
  • BullMQ consumers extend WorkerHost and implement process() — do NOT use the @Process() decorator (that's the older @nestjs/bull API)
  • Register @OnWorkerEvent('completed') and @OnWorkerEvent('failed') lifecycle hooks for observability
  • Set removeOnComplete: true and configure retry with backoff: { type: 'exponential' } on jobs
  • Capture and log job.id from queue.add() return value for traceability
  • Use job.updateProgress() for long-running jobs to enable monitoring dashboards
  • Define and export TypeScript interfaces for all event payloads (e.g., OrderCreatedEvent, UserRegisteredEvent) for type safety across service boundaries

Health Checks

  • Don't just check one thing — include multiple indicators: service connectivity (Redis/DB), memory (heap + RSS), and disk usage
  • Use MicroserviceHealthIndicator for transport checks, MemoryHealthIndicator for heap/RSS, DiskHealthIndicator for storage
  • Configure graceful shutdown timeout: TerminusModule.forRoot({ gracefulShutdownTimeoutMs: 1000 })

OpenAPI / Swagger

The @nestjs/swagger CLI plugin can eliminate most manual @ApiProperty() annotations. Add to nest-cli.json:

{
  "compilerOptions": {
    "plugins": [{
      "name": "@nestjs/swagger",
      "options": { "classValidatorShim": true, "introspectComments": true }
    }]
  }
}

With the plugin enabled, TypeScript types, default values, optional markers, and JSDoc comments are automatically inferred — you only need explicit @ApiProperty() for edge cases.

Testing

  • @suites/unit is now a recommended testing library for NestJS:
    • TestBed.solitary(Service).compile() — all dependencies auto-mocked
    • TestBed.sociable(Service).expose(RealDep).compile() — selected real deps
    • Mocked<T> type for full IntelliSense on mock methods
    • Supports Jest, Vitest, and Sinon
  • For e2e testing, use @nestjs/testing with Test.createTestingModule() and supertest

Custom Decorators

  • For NestJS 10+, prefer Reflector.createDecorator<Role[]>() over SetMetadata for custom decorators — it provides better type inference and eliminates the need for a separate metadata key constant
  • The SetMetadata pattern still works and is fine for simple cases

CLI

Topic Description Reference
CLI Overview Scaffolding, building, and running applications cli-overview
Monorepo & Libraries Workspaces, apps, shared libraries cli-monorepo

Core References

Topic Description Reference
Controllers Route handlers, HTTP methods, request/response handling core-controllers
Modules Application structure, feature modules, shared modules, dynamic modules core-modules
Providers Services, dependency injection, custom providers core-providers
Dependency Injection DI fundamentals, custom providers, scopes core-dependency-injection
Middleware Request/response middleware, functional middleware core-middleware

Fundamentals

Topic Description Reference
Pipes Data transformation and validation pipes fundamentals-pipes
Guards Authorization guards, role-based access control fundamentals-guards
Interceptors Aspect-oriented programming, response transformation fundamentals-interceptors
Exception Filters Error handling, custom exception filters fundamentals-exception-filters
Custom Decorators Creating custom parameter decorators fundamentals-custom-decorators
Dynamic Modules Configurable modules, module configuration fundamentals-dynamic-modules
Execution Context Accessing request context, metadata reflection fundamentals-execution-context
Provider Scopes Singleton, request-scoped, transient providers fundamentals-provider-scopes
Lifecycle Events Application and provider lifecycle hooks fundamentals-lifecycle-events
Lazy Loading Loading modules on-demand for serverless fundamentals-lazy-loading
Circular Dependency Resolving circular dependencies with forwardRef fundamentals-circular-dependency
Module Reference Accessing providers dynamically with ModuleRef fundamentals-module-reference
Testing Unit testing and e2e testing with @nestjs/testing fundamentals-testing

Techniques

Topic Description Reference
Validation ValidationPipe, class-validator, Zod validation techniques-validation
Configuration Environment variables, ConfigModule, configuration management techniques-configuration
Database TypeORM, Prisma, MongoDB integration techniques-database
Caching Keyv-based cache manager, Redis integration techniques-caching
Logging Built-in logger, custom loggers, JSON logging techniques-logging
File Upload File upload handling with multer, validation techniques-file-upload
Versioning URI, header, and media type API versioning techniques-versioning
Serialization Response serialization with class-transformer techniques-serialization
Queues Background job processing with BullMQ techniques-queues
Task Scheduling Cron jobs, intervals, and timeouts techniques-task-scheduling
Events Event-driven architecture with EventEmitter techniques-events
HTTP Module Making HTTP requests with Axios techniques-http-module
Fastify Using Fastify for better performance techniques-fastify
Sessions & Cookies HTTP sessions and cookies for stateful apps techniques-sessions-cookies
Streaming & SSE Compression, file streaming, Server-Sent Events techniques-compression-streaming-sse
MVC & Serve Static Template rendering (Handlebars) and SPA static serving techniques-mvc-serve-static

Security

Topic Description Reference
Authentication Native JWT auth and Passport integration recipes-authentication
Authorization RBAC, claims-based, CASL integration security-authorization
CORS & Rate Limiting CORS, Helmet, ThrottlerModule security-cors-helmet-rate-limiting
Encryption & Hashing bcrypt, argon2, password hashing security-encryption-hashing

OpenAPI

Topic Description Reference
Swagger OpenAPI documentation generation, CLI plugin openapi-swagger

WebSockets

Topic Description Reference
Gateways Real-time communication with Socket.IO/ws websockets-gateways
Guards & Exception Filters WsException, BaseWsExceptionFilter, interceptors, pipes websockets-advanced

Microservices

Topic Description Reference
Overview Transport layers, message patterns, events microservices-overview
gRPC Protocol Buffers, streaming, metadata, reflection microservices-grpc
Transports Redis, Kafka, NATS, RabbitMQ configuration microservices-transports

GraphQL

Topic Description Reference
Overview Code-first and schema-first approaches graphql-overview
Resolvers & Mutations Queries, mutations, field resolvers graphql-resolvers-mutations
Subscriptions Real-time subscriptions with PubSub graphql-subscriptions
Scalars, Unions & Enums Interfaces, scalars, union types, enums graphql-scalars-unions-enums

Recipes

Topic Description Reference
CRUD Generator Nest CLI resource generator recipes-crud-generator
Documentation OpenAPI/Swagger integration recipes-documentation
TypeORM TypeORM integration and usage recipes-typeorm
Prisma Prisma ORM integration recipes-prisma
Mongoose MongoDB with Mongoose ODM recipes-mongoose
CQRS Command Query Responsibility Segregation recipes-cqrs
Terminus Health checks and readiness/liveness probes recipes-terminus

FAQ

Topic Description Reference
Raw Body & Hybrid Webhook signature verification, HTTP + microservices faq-raw-body-hybrid

Best Practices

Topic Description Reference
Request Lifecycle Understanding execution order and flow best-practices-request-lifecycle
Related skills
Installs
7
GitHub Stars
2
First Seen
Mar 28, 2026