# NestJS User Guide

## 1. Quick Start

NestJS is a progressive Node.js framework for building efficient, reliable, and scalable server-side applications. Built with TypeScript and inspired by Angular's architecture, it provides an opinionated application structure based on modules, controllers, and providers with a powerful dependency injection system.

**Key features:**

- TypeScript-first with full JavaScript compatibility
- Modular architecture with dependency injection
- Platform-agnostic HTTP layer (Express or Fastify)
- Built-in support for WebSockets, microservices, and GraphQL
- Extensive decorator-based routing and validation
- Lifecycle hooks for application and module events
- First-class testing support with `@nestjs/testing`
- REPL mode for interactive debugging

**Prerequisites:** Node.js >= 20

```bash
npm i -g @nestjs/cli
nest new my-project
cd my-project
npm run start
```

```text
[Nest] 12345  - 05/07/2026, 10:00:00 AM     LOG [NestFactory] Starting Nest application...
[Nest] 12345  - 05/07/2026, 10:00:00 AM     LOG [NestApplication] Nest application successfully started
```

> [!TIP]
> Use `npm run start:dev` for watch mode during development. The `@nestjs/cli` provides `nest start --watch` which automatically recompiles on file changes.

**What to try next:**

- Add a new controller: see Core Usage below
- Connect a database: see Common Tasks
- Add validation: see the Pipes section
- See the Admin Guide for full architecture and configuration reference

## 2. Installation

### System Requirements

| Requirement | Version |
|---|---|
| Node.js | >= 20 |
| npm | >= 9 (ships with Node 20) |
| TypeScript | 5.x (included) |

### Installation Methods

=== "CLI (Recommended)"
    ```bash
    npm i -g @nestjs/cli
    nest new my-project
    ```

=== "Manual Setup"
    ```bash
    mkdir my-project && cd my-project
    npm init -y
    npm i @nestjs/core @nestjs/common @nestjs/platform-express reflect-metadata rxjs
    npm i -D @nestjs/cli typescript @types/node
    ```

=== "Fastify Platform"
    ```bash
    npm i @nestjs/core @nestjs/common @nestjs/platform-fastify reflect-metadata rxjs
    ```

> [!IMPORTANT]
> The `reflect-metadata` package is required for decorator metadata reflection. It must be imported once in your application entry point (`main.ts`).

### Core Packages

| Package | Purpose |
|---|---|
| `@nestjs/core` | Framework core (DI container, lifecycle, routing) |
| `@nestjs/common` | Decorators, pipes, guards, interceptors, exceptions |
| `@nestjs/platform-express` | Express HTTP adapter (default) |
| `@nestjs/platform-fastify` | Fastify HTTP adapter (alternative) |
| `@nestjs/testing` | Testing utilities |
| `@nestjs/microservices` | Microservice transports (TCP, Redis, NATS, MQTT, RMQ, Kafka, gRPC) |
| `@nestjs/websockets` | WebSocket gateway support |
| `@nestjs/platform-socket.io` | Socket.IO adapter |
| `@nestjs/platform-ws` | WS adapter |

### Post-Install Verification

```bash
nest --version
```

```text
11.0.0
```

```bash
npm run start
```

```text
[Nest] 12345  - LOG [NestFactory] Starting Nest application...
[Nest] 12345  - LOG [RoutesResolver] AppController {/}: +2ms
[Nest] 12345  - LOG [RouterExplorer] Mapped {/, GET} route +1ms
[Nest] 12345  - LOG [NestApplication] Nest application successfully started +1ms
```

### Install Troubleshooting

### Error: `Cannot find module 'reflect-metadata'`

**Cause:** Missing required dependency.

**Solution:**
1. Install `reflect-metadata`:
   ```bash
   npm i reflect-metadata
   ```
2. Ensure it is imported at the top of `main.ts`:
   ```typescript
   import 'reflect-metadata';
   ```

### Error: `Experimental support for decorators is a feature that is subject to change`

**Cause:** TypeScript decorator support not enabled.

**Solution:**
Add to `tsconfig.json`:
```json
{
  "compilerOptions": {
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true
  }
}
```

### Error: `nest: command not found`

**Cause:** NestJS CLI not installed globally or not in PATH.

**Solution:**
```bash
npm i -g @nestjs/cli
```

Or use npx:
```bash
npx @nestjs/cli new my-project
```

## 3. Configuration

NestJS applications are configured programmatically through the `main.ts` bootstrap function and module imports. There is no central configuration file — settings are applied via method calls on the application instance and decorator metadata.

### Bootstrap Configuration

```typescript
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule, {
    logger: ['error', 'warn', 'log'],  // Control log levels
    cors: true,                         // Enable CORS
    abortOnError: false,                // Don't abort on init errors
  });

  app.setGlobalPrefix('api');           // Prefix all routes
  app.enableVersioning({ type: VersioningType.URI }); // API versioning

  await app.listen(3000);
}
bootstrap();
```

### Common Configuration Options

| Option | Type | Default | Description |
|---|---|---|---|
| `logger` | `LogLevel[] \| LoggerService \| false` | All levels | Log output control |
| `cors` | `boolean \| CorsOptions` | `false` | Cross-origin resource sharing |
| `abortOnError` | `boolean` | `true` | Abort on initialization errors |
| `bodyParser` | `boolean` | `true` | Enable built-in body parsing |
| `rawBody` | `boolean` | `false` | Expose raw request body |
| `preview` | `boolean` | `false` | Preview mode (no listeners) |
| `forceCloseConnections` | `boolean` | `false` | Force-close HTTP connections on shutdown |

### Environment Variables

| Variable | Purpose |
|---|---|
| `NO_COLOR` | Disables colored log output when set |
| `NEST_DEBUG` | Enables debug-level DI container logging when set |

> [!TIP]
> For complex configuration, use the dynamic modules pattern with `ConfigModule` from `@nestjs/config` (separate package). See the Dynamic Modules section in Common Tasks for the pattern used to build configurable modules.

See the Admin Guide for the full configuration reference including all versioning types, global prefix options, and platform-specific adapter settings.

## 4. Core Usage

### Modules

Every NestJS application has at least one module — the root `AppModule`. Modules organize the application into cohesive blocks of functionality.

```typescript
import { Module } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';

@Module({
  controllers: [CatsController],
  providers: [CatsService],
  exports: [CatsService],  // Make available to importing modules
})
export class CatsModule {}
```

**`@Module()` options:**

| Property | Description |
|---|---|
| `imports` | Modules whose exported providers are needed in this module |
| `controllers` | Controllers that handle incoming requests |
| `providers` | Services, repositories, and other injectables |
| `exports` | Providers available to modules that import this module |

> [!NOTE]
> Use `@Global()` on a module to make its exports available everywhere without explicit imports. Use sparingly — global modules reduce encapsulation.

### Controllers

Controllers handle incoming requests and return responses. Each controller method is mapped to a route via HTTP method decorators.

```typescript
import {
  Controller, Get, Post, Put, Delete, Patch,
  Body, Param, Query, Headers, Ip,
  HttpCode, Header, Redirect,
} from '@nestjs/common';
import { CreateCatDto } from './dto/create-cat.dto';
import { CatsService } from './cats.service';

@Controller('cats')
export class CatsController {
  constructor(private readonly catsService: CatsService) {}

  @Post()
  @HttpCode(201)
  create(@Body() createCatDto: CreateCatDto) {
    return this.catsService.create(createCatDto);
  }

  @Get()
  findAll(@Query('limit') limit: number) {
    return this.catsService.findAll(limit);
  }

  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.catsService.findOne(id);
  }

  @Put(':id')
  update(@Param('id') id: string, @Body() updateCatDto: any) {
    return this.catsService.update(id, updateCatDto);
  }

  @Delete(':id')
  remove(@Param('id') id: string) {
    return this.catsService.remove(id);
  }
}
```

**HTTP method decorators:**

| Decorator | HTTP Method |
|---|---|
| `@Get()` | GET |
| `@Post()` | POST |
| `@Put()` | PUT |
| `@Delete()` | DELETE |
| `@Patch()` | PATCH |
| `@Options()` | OPTIONS |
| `@Head()` | HEAD |
| `@All()` | All methods |
| `@Search()` | SEARCH |

**Parameter decorators:**

| Decorator | Maps to |
|---|---|
| `@Body(key?)` | `req.body` / `req.body[key]` |
| `@Query(key?)` | `req.query` / `req.query[key]` |
| `@Param(key?)` | `req.params` / `req.params[key]` |
| `@Headers(name?)` | `req.headers` / `req.headers[name]` |
| `@Req()` | Full request object |
| `@Res()` | Full response object |
| `@Session()` | `req.session` |
| `@Ip()` | `req.ip` |
| `@HostParam()` | `req.hosts` |
| `@RawBody()` | Raw request body buffer |

> [!WARNING]
> Using `@Res()` puts the response in library-specific mode — NestJS will not automatically serialize the return value. You must call `res.json()` or `res.send()` manually, or use `@Res({ passthrough: true })` to let NestJS handle the response while still accessing the response object.

### Providers (Services)

Providers are classes annotated with `@Injectable()` that can be injected through the constructor. They encapsulate business logic.

```typescript
import { Injectable } from '@nestjs/common';

@Injectable()
export class CatsService {
  private readonly cats: Cat[] = [];

  create(cat: CreateCatDto): Cat {
    this.cats.push(cat);
    return cat;
  }

  findAll(limit?: number): Cat[] {
    return limit ? this.cats.slice(0, limit) : this.cats;
  }

  findOne(id: string): Cat {
    return this.cats.find(cat => cat.id === id);
  }
}
```

**Custom providers** allow more control over instantiation:

```typescript
@Module({
  providers: [
    { provide: CatsService, useClass: CatsService },       // Standard
    { provide: 'CONFIG', useValue: { debug: true } },       // Value
    { provide: 'ASYNC_CONFIG', useFactory: async () => {    // Factory
        const config = await loadConfig();
        return config;
      },
      inject: [ConfigService],  // Dependencies for factory
    },
    { provide: 'ALIAS', useExisting: CatsService },         // Alias
  ],
})
```

### Middleware

Middleware functions execute before route handlers. They have access to the request and response objects and the `next()` function.

```typescript
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';

@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    console.log(`${req.method} ${req.url}`);
    next();
  }
}
```

Apply middleware in the module:

```typescript
import { Module, MiddlewareConsumer, NestModule } from '@nestjs/common';

@Module({ controllers: [CatsController] })
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(LoggerMiddleware)
      .forRoutes(CatsController);
  }
}
```

### Pipes

Pipes transform or validate input data. NestJS includes several built-in pipes.

**Built-in pipes:**

| Pipe | Purpose |
|---|---|
| `ValidationPipe` | Validates DTOs using `class-validator` |
| `ParseIntPipe` | Parses string to integer |
| `ParseFloatPipe` | Parses string to float |
| `ParseBoolPipe` | Parses string to boolean |
| `ParseArrayPipe` | Parses string to array |
| `ParseUUIDPipe` | Validates and parses UUID strings |
| `ParseEnumPipe` | Validates enum values |
| `DefaultValuePipe` | Provides a default value when parameter is `undefined` |
| `ParseFilePipe` | Validates file uploads |

```typescript
@Get(':id')
findOne(@Param('id', ParseIntPipe) id: number) {
  return this.catsService.findOne(id);
}
```

> [!TIP]
> Apply `ValidationPipe` globally for automatic DTO validation across all routes:
> ```typescript
> app.useGlobalPipes(new ValidationPipe({
>   whitelist: true,        // Strip non-decorated properties
>   transform: true,        // Auto-transform payloads to DTO instances
>   forbidNonWhitelisted: true,  // Throw on extra properties
> }));
> ```

### Guards

Guards determine whether a request should be handled by the route handler. They implement the `CanActivate` interface.

```typescript
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';

@Injectable()
export class AuthGuard implements CanActivate {
  canActivate(context: ExecutionContext): boolean {
    const request = context.switchToHttp().getRequest();
    return !!request.headers.authorization;
  }
}
```

Apply with `@UseGuards()`:

```typescript
@Controller('cats')
@UseGuards(AuthGuard)
export class CatsController {}
```

Or globally:

```typescript
app.useGlobalGuards(new AuthGuard());
```

### Interceptors

Interceptors add extra logic before/after method execution, transform results, handle errors, or extend behavior using RxJS observables.

```typescript
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

@Injectable()
export class TransformInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    return next.handle().pipe(
      map(data => ({ data, timestamp: new Date().toISOString() })),
    );
  }
}
```

Apply with `@UseInterceptors()`:

```typescript
@UseInterceptors(TransformInterceptor)
@Get()
findAll() {
  return this.catsService.findAll();
}
```

### Exception Filters

Exception filters catch unhandled exceptions and format error responses.

```typescript
import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';

@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();
    const status = exception.getStatus();

    response.status(status).json({
      statusCode: status,
      message: exception.message,
      timestamp: new Date().toISOString(),
    });
  }
}
```

**Built-in HTTP exceptions:**

| Exception | Status Code |
|---|---|
| `BadRequestException` | 400 |
| `UnauthorizedException` | 401 |
| `ForbiddenException` | 403 |
| `NotFoundException` | 404 |
| `MethodNotAllowedException` | 405 |
| `NotAcceptableException` | 406 |
| `RequestTimeoutException` | 408 |
| `ConflictException` | 409 |
| `GoneException` | 410 |
| `PayloadTooLargeException` | 413 |
| `UnsupportedMediaTypeException` | 415 |
| `UnprocessableEntityException` | 422 |
| `InternalServerErrorException` | 500 |
| `NotImplementedException` | 501 |
| `BadGatewayException` | 502 |
| `ServiceUnavailableException` | 503 |
| `GatewayTimeoutException` | 504 |
| `ImATeapotException` | 418 |
| `PreconditionFailedException` | 412 |
| `HttpVersionNotSupportedException` | 505 |

```typescript
throw new NotFoundException(`Cat #${id} not found`);
```

### Execution Order

NestJS processes requests through the following pipeline:

```text
Request → Middleware → Guards → Interceptors (before) → Pipes → Route Handler
       → Interceptors (after) → Exception Filters (on error) → Response
```

> [!IMPORTANT]
> The execution order matters for debugging. Guards run after middleware but before pipes. If a guard rejects the request, pipes and the route handler never execute.

## 5. Common Tasks

### Set Up a Database with TypeORM

**Goal:** Connect a NestJS application to a SQL database using TypeORM.

**Prerequisites:** `@nestjs/typeorm`, `typeorm`, database driver (e.g., `mysql2`, `pg`)

**Steps:**

1. Install dependencies:
   ```bash
   npm i @nestjs/typeorm typeorm mysql2
   ```

2. Configure in `AppModule`:
   ```typescript
   import { TypeOrmModule } from '@nestjs/typeorm';

   @Module({
     imports: [
       TypeOrmModule.forRoot({
         type: 'mysql',
         host: 'localhost',
         port: 3306,
         username: 'root',
         password: 'root',
         database: 'test',
         entities: [Photo],
         synchronize: true,  // Disable in production
       }),
       TypeOrmModule.forFeature([Photo]),
     ],
   })
   export class AppModule {}
   ```

3. Create an entity:
   ```typescript
   import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';

   @Entity()
   export class Photo {
     @PrimaryGeneratedColumn()
     id: number;

     @Column()
     name: string;
   }
   ```

4. Inject the repository:
   ```typescript
   @Injectable()
   export class PhotoService {
     constructor(
       @InjectRepository(Photo)
       private readonly photoRepo: Repository<Photo>,
     ) {}
   }
   ```

> [!WARNING]
> Never use `synchronize: true` in production — it can cause data loss. Use TypeORM migrations instead.

### Set Up a Database with Mongoose

**Goal:** Connect to MongoDB using Mongoose.

**Prerequisites:** `@nestjs/mongoose`, `mongoose`

```bash
npm i @nestjs/mongoose mongoose
```

```typescript
import { MongooseModule } from '@nestjs/mongoose';

@Module({
  imports: [
    MongooseModule.forRoot('mongodb://localhost/test'),
    MongooseModule.forFeature([{ name: Cat.name, schema: CatSchema }]),
  ],
})
export class AppModule {}
```

### JWT Authentication

**Goal:** Add JWT-based authentication.

**Prerequisites:** `@nestjs/passport`, `passport`, `passport-jwt`, `@nestjs/jwt`

1. Create an auth module:
   ```typescript
   @Module({
     imports: [
       JwtModule.register({
         secret: 'your-secret-key',
         signOptions: { expiresIn: '1h' },
       }),
     ],
     providers: [AuthService, JwtStrategy],
     exports: [AuthService],
   })
   export class AuthModule {}
   ```

2. Create a JWT strategy:
   ```typescript
   @Injectable()
   export class JwtStrategy extends PassportStrategy(Strategy) {
     constructor() {
       super({
         jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
         secretOrKey: 'your-secret-key',
       });
     }

     async validate(payload: any) {
       return { userId: payload.sub, username: payload.username };
     }
   }
   ```

3. Protect routes with `@UseGuards(AuthGuard('jwt'))`.

### File Upload

**Goal:** Handle file uploads using multer.

```typescript
import { FileInterceptor, FilesInterceptor } from '@nestjs/platform-express';
import { UploadedFile, UploadedFiles } from '@nestjs/common';

@Controller('upload')
export class UploadController {
  @Post('single')
  @UseInterceptors(FileInterceptor('file'))
  uploadFile(@UploadedFile() file: Express.Multer.File) {
    return { filename: file.originalname, size: file.size };
  }

  @Post('multiple')
  @UseInterceptors(FilesInterceptor('files', 10))
  uploadFiles(@UploadedFiles() files: Express.Multer.File[]) {
    return files.map(f => ({ filename: f.originalname }));
  }
}
```

### Server-Sent Events (SSE)

**Goal:** Stream real-time updates to clients.

```typescript
import { Controller, Sse } from '@nestjs/common';
import { Observable, interval, map } from 'rxjs';

@Controller()
export class SseController {
  @Sse('events')
  events(): Observable<MessageEvent> {
    return interval(1000).pipe(
      map(() => ({ data: { timestamp: Date.now() } } as MessageEvent)),
    );
  }
}
```

### Serve Static Files

**Goal:** Serve a frontend SPA alongside the API.

```bash
npm i @nestjs/serve-static
```

```typescript
import { ServeStaticModule } from '@nestjs/serve-static';
import { join } from 'path';

@Module({
  imports: [
    ServeStaticModule.forRoot({
      rootPath: join(__dirname, '..', 'client'),
    }),
  ],
})
export class AppModule {}
```

### WebSocket Gateway

**Goal:** Add real-time bidirectional communication.

```bash
npm i @nestjs/websockets @nestjs/platform-socket.io socket.io
```

```typescript
import {
  WebSocketGateway,
  SubscribeMessage,
  MessageBody,
  WebSocketServer,
  ConnectedSocket,
} from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';

@WebSocketGateway({ cors: true })
export class EventsGateway {
  @WebSocketServer()
  server: Server;

  @SubscribeMessage('message')
  handleMessage(
    @MessageBody() data: string,
    @ConnectedSocket() client: Socket,
  ): string {
    this.server.emit('broadcast', data);
    return 'Message received';
  }
}
```

### Microservices (TCP Transport)

**Goal:** Create a microservice communicating over TCP.

```typescript
// main.ts (microservice)
import { NestFactory } from '@nestjs/core';
import { Transport, MicroserviceOptions } from '@nestjs/microservices';

async function bootstrap() {
  const app = await NestFactory.createMicroservice<MicroserviceOptions>(
    AppModule,
    { transport: Transport.TCP, options: { host: '0.0.0.0', port: 3001 } },
  );
  await app.listen();
}
bootstrap();
```

```typescript
// Controller handling messages
@Controller()
export class MathController {
  @MessagePattern({ cmd: 'sum' })
  sum(data: number[]): number {
    return data.reduce((a, b) => a + b, 0);
  }

  @EventPattern('user_created')
  handleUserCreated(data: any) {
    // Handle event (fire-and-forget)
  }
}
```

### Dynamic Modules

**Goal:** Create a reusable, configurable module.

```typescript
import { DynamicModule, Module } from '@nestjs/common';

@Module({})
export class ConfigModule {
  static forRoot(options: ConfigOptions): DynamicModule {
    return {
      module: ConfigModule,
      providers: [
        { provide: 'CONFIG_OPTIONS', useValue: options },
        ConfigService,
      ],
      exports: [ConfigService],
      global: true,
    };
  }
}
```

> [!TIP]
> For complex dynamic modules, use `ConfigurableModuleBuilder` from `@nestjs/common` to auto-generate `forRoot()` and `forRootAsync()` static methods with less boilerplate.

### MVC with Templates

**Goal:** Render server-side views using a template engine.

```typescript
// main.ts
const app = await NestFactory.create(AppModule);
app.setBaseViewsDir(join(__dirname, '..', 'views'));
app.setViewEngine('hbs');
```

```typescript
@Controller()
export class AppController {
  @Get()
  @Render('index')
  root() {
    return { message: 'Hello World' };
  }
}
```

### Using StreamableFile for File Downloads

```typescript
import { StreamableFile } from '@nestjs/common';
import { createReadStream } from 'fs';
import { join } from 'path';

@Controller('files')
export class FilesController {
  @Get('download')
  getFile(): StreamableFile {
    const file = createReadStream(join(process.cwd(), 'package.json'));
    return new StreamableFile(file);
  }
}
```

### API Versioning

```typescript
import { VersioningType } from '@nestjs/common';

const app = await NestFactory.create(AppModule);
app.enableVersioning({ type: VersioningType.URI });
```

```typescript
@Controller({ path: 'cats', version: '1' })
export class CatsV1Controller { /* ... */ }

@Controller({ path: 'cats', version: '2' })
export class CatsV2Controller { /* ... */ }
```

**Versioning types:**

| Type | Example URL |
|---|---|
| `VersioningType.URI` | `/v1/cats` |
| `VersioningType.HEADER` | Header: `X-API-Version: 1` |
| `VersioningType.MEDIA_TYPE` | `Accept: application/json;v=1` |
| `VersioningType.CUSTOM` | Custom extraction logic |

### Using Swagger/OpenAPI

```bash
npm i @nestjs/swagger
```

```typescript
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';

const config = new DocumentBuilder()
  .setTitle('Cats API')
  .setDescription('The cats API description')
  .setVersion('1.0')
  .addBearerAuth()
  .build();

const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api-docs', app, document);
```

### GraphQL (Code-First)

```bash
npm i @nestjs/graphql @nestjs/apollo @apollo/server graphql
```

```typescript
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { GraphQLModule } from '@nestjs/graphql';

@Module({
  imports: [
    GraphQLModule.forRoot<ApolloDriverConfig>({
      driver: ApolloDriver,
      autoSchemaFile: join(process.cwd(), 'schema.gql'),
    }),
  ],
})
export class AppModule {}
```

### Class Serialization

Control what properties are exposed in responses:

```typescript
import { ClassSerializerInterceptor, UseInterceptors } from '@nestjs/common';
import { Exclude, Expose } from 'class-transformer';

export class UserEntity {
  id: number;
  name: string;

  @Exclude()
  password: string;

  constructor(partial: Partial<UserEntity>) {
    Object.assign(this, partial);
  }
}

@Controller('users')
@UseInterceptors(ClassSerializerInterceptor)
export class UsersController {
  @Get(':id')
  findOne(@Param('id') id: string): UserEntity {
    return new UserEntity({ id: 1, name: 'John', password: 'secret' });
  }
}
```

## 6. Troubleshooting

### Error: `Nest can't resolve dependencies of the X`

**Cause:** A provider's dependency is not available in the current module scope. The DI container cannot find a provider for the required injection token.

**Solution:**
1. Ensure the dependency is listed in the `providers` array of the module
2. If the dependency lives in another module, import that module and ensure it exports the provider
3. For circular dependencies, use `forwardRef()`:
   ```typescript
   @Inject(forwardRef(() => CatsService))
   ```

**Prevention:** Keep module boundaries clear. Export only what other modules need.

### Error: `Unknown element` or `Unknown module`

**Cause:** A module or provider is imported but not properly decorated or not a valid NestJS module.

**Solution:**
1. Verify the class has the `@Module()` decorator
2. Check for typos in import paths
3. Ensure circular module dependencies use `forwardRef()`

### Error: `Cannot GET /path`

**Cause:** No route handler matches the requested path.

**Solution:**
1. Check the controller has `@Controller('prefix')` with the correct prefix
2. Verify the route decorator (`@Get()`, `@Post()`, etc.) path matches
3. If using global prefix, account for it: `app.setGlobalPrefix('api')` means routes become `/api/...`
4. Check if versioning is enabled — routes may require version prefix

### Application hangs on shutdown

**Cause:** Open connections or long-running tasks preventing graceful shutdown.

**Solution:**
1. Enable shutdown hooks:
   ```typescript
   app.enableShutdownHooks();
   ```
2. Implement `OnApplicationShutdown` in providers that hold connections:
   ```typescript
   @Injectable()
   export class DbService implements OnApplicationShutdown {
     onApplicationShutdown(signal?: string) {
       return this.connection.close();
     }
   }
   ```

**Prevention:** Always clean up resources in lifecycle hooks.

### Error: `Circular dependency between modules`

**Cause:** Module A imports Module B, which imports Module A.

**Solution:**
Use `forwardRef()` in both module imports:
```typescript
@Module({
  imports: [forwardRef(() => ModuleB)],
})
export class ModuleA {}
```

> [!WARNING]
> Circular dependencies are a design smell. Refactor to extract shared functionality into a third module when possible.

### Validation errors not thrown

**Cause:** `ValidationPipe` not applied or `class-validator` decorators missing.

**Solution:**
1. Install required packages: `npm i class-validator class-transformer`
2. Apply `ValidationPipe` globally or at the controller/method level
3. Add validation decorators to DTO classes:
   ```typescript
   import { IsString, IsInt, Min } from 'class-validator';

   export class CreateCatDto {
     @IsString()
     name: string;

     @IsInt()
     @Min(0)
     age: number;
   }
   ```

### WebSocket connection refused

**Cause:** WebSocket gateway not properly registered or CORS blocking the connection.

**Solution:**
1. Ensure the gateway class is registered in a module's `providers`
2. Enable CORS on the gateway:
   ```typescript
   @WebSocketGateway({ cors: { origin: '*' } })
   ```

### Fastify middleware not working (nestjs/nest#11802)

**Cause:** Fastify middleware doesn't apply correctly when matched against routes registered via a Fastify plugin.

**Solution:** Register middleware before Fastify plugins, or use NestJS-level middleware (`NestMiddleware`) instead of Fastify-native middleware for routes managed by NestJS controllers.

## 7. FAQ

**Q: How do I switch from Express to Fastify?**

Replace `@nestjs/platform-express` with `@nestjs/platform-fastify` and update `main.ts`:
```typescript
import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify';

const app = await NestFactory.create<NestFastifyApplication>(
  AppModule,
  new FastifyAdapter(),
);
await app.listen(3000, '0.0.0.0');  // Fastify listens on localhost only by default
```

**Q: What are injection scopes and when should I use them?**

NestJS supports three scopes: `DEFAULT` (singleton), `REQUEST` (per-request instance), and `TRANSIENT` (new instance per injection). Most providers should use `DEFAULT`. Use `REQUEST` when you need per-request state (e.g., multi-tenant context). Use `TRANSIENT` when each consumer needs its own instance.

```typescript
@Injectable({ scope: Scope.REQUEST })
export class RequestScopedService {}
```

**Q: How do I create a hybrid application (HTTP + microservice)?**

```typescript
const app = await NestFactory.create(AppModule);
app.connectMicroservice<MicroserviceOptions>({
  transport: Transport.TCP,
  options: { port: 3001 },
});
await app.startAllMicroservices();
await app.listen(3000);
```

**Q: How do I use the REPL mode?**

```typescript
import { repl } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  await repl(AppModule);
}
bootstrap();
```

This starts an interactive shell where you can call methods on any provider, inspect the DI container, and debug the application.

**Q: How do I set up hot module replacement (HMR)?**

Use the `webpack-hmr.config.js` with `@nestjs/cli` or, for ESM projects, configure HMR in `main.ts`:

```typescript
declare const module: any;

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);

  if (module.hot) {
    module.hot.accept();
    module.hot.dispose(() => app.close());
  }
}
bootstrap();
```

**Q: What lifecycle hooks are available?**

Hooks execute in this order during startup and shutdown:

| Hook | When |
|---|---|
| `onModuleInit` | After the module's providers are instantiated |
| `onApplicationBootstrap` | After all modules are initialized |
| `onModuleDestroy` | When `close()` is called (reverse order) |
| `beforeApplicationShutdown` | After `onModuleDestroy`, before connections close |
| `onApplicationShutdown` | After all connections are closed |

**Q: How do I handle CORS?**

```typescript
const app = await NestFactory.create(AppModule);
app.enableCors({
  origin: ['https://example.com'],
  methods: 'GET,POST',
  credentials: true,
});
```

**Q: Can I use NestJS with Babel instead of TypeScript?**

Yes. NestJS provides a Babel example (`sample/09-babel-example`). Use `@babel/plugin-proposal-decorators` and `@babel/plugin-proposal-class-properties` for decorator support.

**Q: How do I test NestJS applications?**

Use `@nestjs/testing` to create a testing module:

```typescript
import { Test, TestingModule } from '@nestjs/testing';

describe('CatsController', () => {
  let controller: CatsController;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      controllers: [CatsController],
      providers: [CatsService],
    }).compile();

    controller = module.get<CatsController>(CatsController);
  });

  it('should return all cats', () => {
    expect(controller.findAll()).toBeDefined();
  });
});
```

**Q: How do I use gRPC with NestJS?**

```typescript
const app = await NestFactory.createMicroservice<MicroserviceOptions>(
  AppModule,
  {
    transport: Transport.GRPC,
    options: {
      package: 'hero',
      protoPath: join(__dirname, 'hero/hero.proto'),
    },
  },
);
```

Define handlers with `@GrpcMethod()`:

```typescript
@Controller()
export class HeroController {
  @GrpcMethod('HeroService', 'FindOne')
  findOne(data: { id: number }): Hero {
    return { id: data.id, name: 'Hero' };
  }
}
```

---

_Generated May 2026 from nestjs/nest at 4b6420b. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
