LearnThatStack Ace your next interview

NestJS.
Interview cheat sheet.

Quick reference for NestJS - sectioned for fast scanning. Skim the part you're shaky on, walk in confident.

Backend Development 18-section reference ~13 min read

Summary

NestJS is a progressive Node.js framework built with TypeScript that provides a robust foundation for building scalable server-side applications. Inspired by Angular's architecture, it combines elements of OOP, FP, and FRP. This cheatsheet covers core NestJS concepts including modules, controllers, providers, dependency injection, middleware, guards, pipes, interceptors, exception handling, database integration with TypeORM, authentication with Passport, testing strategies, microservices, and best practices for enterprise-grade applications.

1. Introduction & Core Concepts

What is NestJS?

  • Progressive Node.js framework built with TypeScript
  • Uses Express/Fastify under the hood
  • Inspired by Angular's architecture
  • Follows SOLID principles and MVC pattern

Key Features

  • Modular Architecture: Organize code into modules
  • Dependency Injection: IoC container manages dependencies
  • Decorators: TypeScript decorators for metadata
  • Platform Agnostic: Works with Express, Fastify, etc.

2. Project Setup

# Install CLI
npm i -g @nestjs/cli

# Create new project
nest new project-name

# Generate resources
nest g module users
nest g controller users
nest g service users

3. Controllers

Basic Controller

@Controller('users')
export class UsersController {
  @Get()
  findAll(): string {
    return 'All users';
  }

  @Get(':id')
  findOne(@Param('id') id: string): string {
    return `User ${id}`;
  }

  @Post()
  create(@Body() createUserDto: CreateUserDto) {
    return 'User created';
  }

  @Put(':id')
  update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) {
    return `Updated user ${id}`;
  }

  @Delete(':id')
  remove(@Param('id') id: string) {
    return `Removed user ${id}`;
  }
}

Request Decorators

  • @Param() - Route parameters
  • @Query() - Query parameters
  • @Body() - Request body
  • @Headers() - Request headers
  • @Req() - Full request object
  • @Res() - Response object

4. Providers/Services

Basic Service

@Injectable()
export class UsersService {
  private users = [];

  findAll() {
    return this.users;
  }

  findOne(id: number) {
    return this.users.find(user => user.id === id);
  }

  create(user: any) {
    this.users.push(user);
    return user;
  }
}

Dependency Injection

@Controller('users')
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Get()
  findAll() {
    return this.usersService.findAll();
  }
}

5. Modules

Module Structure

@Module({
  imports: [DatabaseModule],     // Other modules
  controllers: [UsersController], // Controllers
  providers: [UsersService],      // Services/Providers
  exports: [UsersService]         // Exported providers
})
export class UsersModule {}

Root Module

@Module({
  imports: [UsersModule, ProductsModule],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

6. Middleware

Custom Middleware

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

// Apply in module
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(LoggerMiddleware)
      .forRoutes('*');
  }
}

7. Guards

Authorization Guard

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

// Usage
@Controller('users')
@UseGuards(AuthGuard)
export class UsersController {}

8. Interceptors

Response Transform Interceptor

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

// Usage
@UseInterceptors(TransformInterceptor)
@Controller('users')
export class UsersController {}

9. Pipes

Validation Pipe

// DTO with class-validator
export class CreateUserDto {
  @IsString()
  @IsNotEmpty()
  name: string;

  @IsEmail()
  email: string;

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

// Global validation pipe
app.useGlobalPipes(new ValidationPipe());

// Controller method
@Post()
create(@Body() createUserDto: CreateUserDto) {
  return this.usersService.create(createUserDto);
}

Custom Pipe

@Injectable()
export class ParseIntPipe implements PipeTransform<string, number> {
  transform(value: string): number {
    const val = parseInt(value, 10);
    if (isNaN(val)) {
      throw new BadRequestException('Validation failed');
    }
    return val;
  }
}

10. Exception Filters

Custom Exception Filter

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

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

// Usage
@UseFilters(HttpExceptionFilter)
@Controller('users')
export class UsersController {}

11. Database Integration

TypeORM Setup

// app.module.ts
@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'postgres',
      host: 'localhost',
      port: 5432,
      username: 'test',
      password: 'test',
      database: 'test',
      entities: [User],
      synchronize: true,
    }),
    UsersModule,
  ],
})
export class AppModule {}

Entity

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

  @Column()
  name: string;

  @Column({ unique: true })
  email: string;

  @CreateDateColumn()
  createdAt: Date;
}

Repository Pattern

@Injectable()
export class UsersService {
  constructor(
    @InjectRepository(User)
    private usersRepository: Repository<User>,
  ) {}

  findAll(): Promise<User[]> {
    return this.usersRepository.find();
  }

  findOne(id: number): Promise<User> {
    return this.usersRepository.findOne({ where: { id } });
  }

  create(user: CreateUserDto): Promise<User> {
    return this.usersRepository.save(user);
  }
}

12. Authentication

JWT Strategy

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor() {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      ignoreExpiration: false,
      secretOrKey: 'secret',
    });
  }

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

// Auth Service
@Injectable()
export class AuthService {
  constructor(
    private usersService: UsersService,
    private jwtService: JwtService
  ) {}

  async login(user: any) {
    const payload = { username: user.username, sub: user.userId };
    return {
      access_token: this.jwtService.sign(payload),
    };
  }
}

13. Testing

Unit Testing

describe('UsersService', () => {
  let service: UsersService;

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

    service = module.get<UsersService>(UsersService);
  });

  it('should be defined', () => {
    expect(service).toBeDefined();
  });

  it('should create a user', () => {
    const user = { name: 'John', email: 'john@example.com' };
    expect(service.create(user)).toEqual(user);
  });
});

E2E Testing

describe('UsersController (e2e)', () => {
  let app: INestApplication;

  beforeEach(async () => {
    const moduleFixture = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    app = moduleFixture.createNestApplication();
    await app.init();
  });

  it('/users (GET)', () => {
    return request(app.getHttpServer())
      .get('/users')
      .expect(200)
      .expect([]);
  });
});

14. Advanced Concepts

Custom Decorators

// Create decorator
export const User = createParamDecorator(
  (data: unknown, ctx: ExecutionContext) => {
    const request = ctx.switchToHttp().getRequest();
    return request.user;
  },
);

// Usage
@Get('profile')
getProfile(@User() user: UserEntity) {
  return user;
}

Dynamic Modules

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

Microservices

// Main.ts for microservice
const app = await NestFactory.createMicroservice<MicroserviceOptions>(
  AppModule,
  {
    transport: Transport.TCP,
    options: {
      host: '127.0.0.1',
      port: 8877,
    },
  },
);

// Message pattern
@MessagePattern('sum')
accumulate(data: number[]): number {
  return data.reduce((a, b) => a + b);
}

15. Best Practices

1. Use DTOs for Type Safety

export class CreateUserDto {
  @IsString()
  name: string;
  
  @IsEmail()
  email: string;
}

2. Implement Error Handling

@Get(':id')
async findOne(@Param('id') id: string) {
  const user = await this.usersService.findOne(id);
  if (!user) {
    throw new NotFoundException('User not found');
  }
  return user;
}

3. Use Configuration Module

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      envFilePath: '.env',
    }),
  ],
})
export class AppModule {}

4. Implement Logging

@Injectable()
export class MyService {
  private readonly logger = new Logger(MyService.name);

  doSomething() {
    this.logger.log('Doing something...');
  }
}

5. Use Async/Await

@Get()
async findAll(): Promise<User[]> {
  return await this.usersService.findAll();
}

16. Key Concepts & Comparisons

NestJS Component Hierarchy & Execution Order

Order Component Purpose Access Return Type
1 Middleware Request preprocessing req/res objects void
2 Guards Authentication/Authorization ExecutionContext boolean/Promise
3 Interceptors (Before) Pre-processing, logging ExecutionContext, CallHandler Observable
4 Pipes Validation, transformation Input value Transformed value
5 Route Handler Business logic Processed inputs Response data
6 Interceptors (After) Post-processing, formatting Response data Modified response
7 Exception Filters Error handling Exception, ArgumentsHost Error response

Middleware vs Guards vs Interceptors

Aspect Middleware Guards Interceptors
Execution Time Before all NestJS components After middleware, before handler Before and after handler
Access to req, res, next ExecutionContext ExecutionContext, CallHandler
Primary Use Request parsing, logging, CORS Authentication, authorization Transform data, logging, caching
Return Type void (calls next()) boolean Observable
Can Modify Response Yes (via res object) No Yes (via Observable operators)
Error Handling Manual try-catch Throw exceptions Automatic via Observable

Dependency Injection Scopes

Scope Lifecycle Use Case Memory Impact Example
Singleton One instance per application Stateless services, utilities Low Database connections, configs
Request New instance per request Request-specific data Medium User context, request logging
Transient New instance every time injected Stateful operations High File processors, calculators

Provider Registration Patterns

Pattern Syntax Use Case Benefits
Class Provider providers: [UserService] Standard service injection Type safety, automatic instantiation
Value Provider { provide: 'CONFIG', useValue: config } Constants, configuration Simple value injection
Factory Provider { provide: 'DB', useFactory: createDB } Dynamic creation logic Runtime configuration
Async Provider { provide: 'ASYNC', useFactory: async () => {...} } Async initialization Database connections

Module Types & Organization

Module Type Purpose Characteristics Example
Feature Module Business domain logic Encapsulates related functionality UsersModule, OrdersModule
Shared Module Common functionality Exported providers for reuse DatabaseModule, ConfigModule
Core Module App-wide singletons Global providers, typically imported once AuthModule, LoggerModule
Dynamic Module Configurable modules Runtime configuration ConfigModule.forRoot(options)

HTTP Decorators & Use Cases

Decorator HTTP Method Idempotent Safe Use Case
@Get() GET Yes Yes Retrieve data
@Post() POST No No Create resources
@Put() PUT Yes No Update/replace resource
@Patch() PATCH No No Partial update
@Delete() DELETE Yes No Remove resource
@Options() OPTIONS Yes Yes Preflight requests
@Head() HEAD Yes Yes Metadata only

Parameter Decorators

Decorator Source Type Example Usage
@Param() URL path Route parameters @Param('id') id: string
@Query() Query string Query parameters @Query('search') search: string
@Body() Request body JSON payload @Body() createDto: CreateUserDto
@Headers() HTTP headers Header values @Headers('authorization') auth: string
@Req() Express request Full request object @Req() request: Request
@Res() Express response Full response object @Res() response: Response

Validation Strategies

Strategy Implementation Pros Cons Use Case
Class Validator DTO with decorators Type-safe, declarative Additional dependency API input validation
Joi Schema Schema objects Flexible, runtime No compile-time checking Configuration validation
Custom Pipes Manual validation logic Full control More code Complex business rules
Transform Pipes Built-in transformations Simple, fast Limited functionality Type conversion

Error Handling Patterns

Pattern Implementation Use Case Benefits
Built-in Exceptions throw new NotFoundException() Standard HTTP errors Consistent response format
Custom Exceptions Extend HttpException Business-specific errors Domain-specific messaging
Exception Filters @Catch() decorator Cross-cutting error handling Centralized error processing
Global Filters app.useGlobalFilters() Application-wide handling Consistent error responses

Database Integration Patterns

Pattern ORM Implementation Use Case
Repository Pattern TypeORM @InjectRepository() Standard CRUD operations
Active Record TypeORM Entity methods Simple operations
Query Builder TypeORM Fluent API Complex queries
Raw Queries TypeORM SQL strings Performance-critical operations
Mongoose Mongoose Schema-based MongoDB integration

Authentication Strategies

Strategy Implementation Use Case Security Level
JWT @nestjs/jwt + Passport Stateless API auth High
Session Express sessions Web applications Medium
OAuth2 Passport strategies Third-party auth High
API Keys Custom guards Service-to-service Medium
Basic Auth Passport basic Simple scenarios Low

Testing Strategies

Test Type Scope Tools Focus
Unit Tests Individual components Jest, Testing module Business logic
Integration Tests Module interactions TestingModule Component integration
E2E Tests Full application Supertest User workflows
Contract Tests API contracts Pact, OpenAPI API compatibility

Performance Optimization Techniques

Technique Implementation Impact Use Case
Caching @nestjs/cache-manager High Frequent data access
Compression Middleware Medium Reduce bandwidth
Rate Limiting @nestjs/throttler Security/Performance API protection
Database Indexing ORM configuration High Query optimization
Connection Pooling Database config Medium Concurrent requests
Lazy Loading Dynamic imports Medium Startup time

Microservices Communication

Transport Protocol Use Case Characteristics
TCP TCP sockets High performance Fast, binary protocol
Redis Pub/Sub Scalable messaging Message queuing
NATS NATS protocol Cloud-native Lightweight, resilient
RabbitMQ AMQP Enterprise messaging Reliable, feature-rich
gRPC HTTP/2 Service mesh Type-safe, efficient

Security Best Practices Implementation

Security Aspect NestJS Implementation Purpose
Input Validation ValidationPipe with class-validator Prevent injection attacks
Rate Limiting ThrottlerModule Prevent abuse
CORS Enable CORS middleware Control cross-origin requests
Helmet Security headers middleware Protect against attacks
Authentication Guards with Passport Verify user identity
Authorization Role-based guards Control resource access
HTTPS Express/Fastify configuration Encrypt data in transit

Quick Reference & Best Practices

Essential NestJS CLI Commands

Command Description Example
nest new <name> Create new project nest new my-app
nest g module <name> Generate module nest g module users
nest g controller <name> Generate controller nest g controller users
nest g service <name> Generate service nest g service users
nest g guard <name> Generate guard nest g guard auth
nest g pipe <name> Generate pipe nest g pipe validation
nest g filter <name> Generate exception filter nest g filter http-exception
nest g interceptor <name> Generate interceptor nest g interceptor transform
nest g middleware <name> Generate middleware nest g middleware logger
nest g decorator <name> Generate custom decorator nest g decorator user

Core Decorators Reference

Category Decorator Purpose Example
Class @Controller(path) Define controller @Controller('users')
Class @Injectable() Mark as injectable service @Injectable()
Class @Module(metadata) Define module @Module({ imports: [...] })
Method @Get(path) Handle GET requests @Get(':id')
Method @Post(path) Handle POST requests @Post()
Method @Put(path) Handle PUT requests @Put(':id')
Method @Delete(path) Handle DELETE requests @Delete(':id')
Parameter @Body() Extract request body @Body() dto: CreateUserDto
Parameter @Param(key) Extract route parameter @Param('id') id: string
Parameter @Query(key) Extract query parameter @Query('search') search: string
Enhancement @UseGuards(guard) Apply guard @UseGuards(AuthGuard)
Enhancement @UseInterceptors(interceptor) Apply interceptor @UseInterceptors(LoggingInterceptor)

TypeORM Entity Quick Reference

@Entity('users')
export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column({ unique: true })
  email: string;

  @Column()
  name: string;

  @Column({ nullable: true })
  profilePicture?: string;

  @CreateDateColumn()
  createdAt: Date;

  @UpdateDateColumn()
  updatedAt: Date;

  @OneToMany(() => Order, order => order.user)
  orders: Order[];

  @ManyToOne(() => Role, role => role.users)
  role: Role;
}

Validation Pipe Configuration

// Global validation setup
app.useGlobalPipes(new ValidationPipe({
  whitelist: true,           // Strip non-whitelisted properties
  forbidNonWhitelisted: true, // Throw error for non-whitelisted properties
  transform: true,           // Auto-transform payloads to DTO instances
  transformOptions: {
    enableImplicitConversion: true, // Allow type conversion
  },
}));

// DTO with validation decorators
export class CreateUserDto {
  @IsString()
  @IsNotEmpty()
  @Length(2, 50)
  name: string;

  @IsEmail()
  email: string;

  @IsOptional()
  @IsString()
  @Length(8, 100)
  password?: string;

  @IsInt()
  @Min(18)
  @Max(120)
  age: number;

  @IsArray()
  @ArrayNotEmpty()
  @IsString({ each: true })
  roles: string[];
}

Security Implementation Checklist

// 1. Enable CORS
app.enableCors({
  origin: ['http://localhost:3000'],
  credentials: true,
});

// 2. Add security headers
app.use(helmet());

// 3. Rate limiting
app.use(
  rateLimit({
    windowMs: 15 * 60 * 1000, // 15 minutes
    max: 100, // limit each IP to 100 requests per windowMs
  }),
);

// 4. Global validation
app.useGlobalPipes(new ValidationPipe({
  whitelist: true,
  transform: true,
}));

// 5. Authentication guard
@UseGuards(JwtAuthGuard)
@Controller('protected')
export class ProtectedController {}

// 6. Role-based authorization
@Roles('admin')
@UseGuards(JwtAuthGuard, RolesGuard)
@Delete(':id')
deleteUser() {}

Error Handling Best Practices

// Custom business exception
export class UserAlreadyExistsException extends ConflictException {
  constructor(email: string) {
    super(`User with email ${email} already exists`);
  }
}

// Global exception filter
@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
  private readonly logger = new Logger(AllExceptionsFilter.name);

  catch(exception: unknown, host: ArgumentsHost): void {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();

    let status = HttpStatus.INTERNAL_SERVER_ERROR;
    let message = 'Internal server error';

    if (exception instanceof HttpException) {
      status = exception.getStatus();
      message = exception.message;
    }

    this.logger.error(`${request.method} ${request.url}`, exception);

    response.status(status).json({
      statusCode: status,
      timestamp: new Date().toISOString(),
      path: request.url,
      message,
    });
  }
}

Testing Patterns

// Unit test with mocked dependencies
describe('UsersService', () => {
  let service: UsersService;
  let repository: Repository<User>;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        UsersService,
        {
          provide: getRepositoryToken(User),
          useValue: {
            find: jest.fn(),
            findOne: jest.fn(),
            save: jest.fn(),
            delete: jest.fn(),
          },
        },
      ],
    }).compile();

    service = module.get<UsersService>(UsersService);
    repository = module.get<Repository<User>>(getRepositoryToken(User));
  });

  it('should find all users', async () => {
    const users = [{ id: 1, name: 'John' }];
    jest.spyOn(repository, 'find').mockResolvedValue(users);

    expect(await service.findAll()).toEqual(users);
  });
});

// Integration test
describe('UsersController (e2e)', () => {
  let app: INestApplication;

  beforeEach(async () => {
    const moduleFixture = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    app = moduleFixture.createNestApplication();
    await app.init();
  });

  it('/users (POST)', () => {
    return request(app.getHttpServer())
      .post('/users')
      .send({ name: 'John', email: 'john@example.com' })
      .expect(201);
  });
});

Performance Optimization Strategies

// 1. Caching with Redis
@Injectable()
export class UsersService {
  constructor(
    @InjectRepository(User)
    private usersRepository: Repository<User>,
    @Inject(CACHE_MANAGER)
    private cacheManager: Cache,
  ) {}

  async findOne(id: number): Promise<User> {
    const cacheKey = `user:${id}`;
    const cached = await this.cacheManager.get<User>(cacheKey);
    
    if (cached) {
      return cached;
    }

    const user = await this.usersRepository.findOne({ where: { id } });
    await this.cacheManager.set(cacheKey, user, { ttl: 300 });
    
    return user;
  }
}

// 2. Database query optimization
@Injectable()
export class UsersService {
  async getUsersWithOrders(): Promise<User[]> {
    return this.usersRepository.find({
      relations: ['orders'],
      select: ['id', 'name', 'email'], // Only select needed fields
      take: 50, // Limit results
    });
  }
}

// 3. Async initialization
@Injectable()
export class DatabaseService implements OnModuleInit {
  async onModuleInit() {
    await this.connect();
  }
  
  private async connect() {
    // Async initialization logic
  }
}

Configuration Management

// config/configuration.ts
export default () => ({
  port: parseInt(process.env.PORT, 10) || 3000,
  database: {
    host: process.env.DATABASE_HOST,
    port: parseInt(process.env.DATABASE_PORT, 10) || 5432,
    username: process.env.DATABASE_USERNAME,
    password: process.env.DATABASE_PASSWORD,
    name: process.env.DATABASE_NAME,
  },
  jwt: {
    secret: process.env.JWT_SECRET,
    expiresIn: process.env.JWT_EXPIRES_IN || '1h',
  },
});

// app.module.ts
@Module({
  imports: [
    ConfigModule.forRoot({
      load: [configuration],
      isGlobal: true,
      validationSchema: Joi.object({
        NODE_ENV: Joi.string().valid('development', 'production', 'test').required(),
        PORT: Joi.number().default(3000),
        DATABASE_HOST: Joi.string().required(),
        JWT_SECRET: Joi.string().required(),
      }),
    }),
  ],
})
export class AppModule {}

Essential Package Dependencies

{
  "dependencies": {
    "@nestjs/common": "^10.0.0",
    "@nestjs/core": "^10.0.0",
    "@nestjs/platform-express": "^10.0.0",
    "@nestjs/config": "^3.0.0",
    "@nestjs/typeorm": "^10.0.0",
    "@nestjs/jwt": "^10.0.0",
    "@nestjs/passport": "^10.0.0",
    "@nestjs/swagger": "^7.0.0",
    "class-validator": "^0.14.0",
    "class-transformer": "^0.5.0",
    "passport": "^0.6.0",
    "passport-jwt": "^4.0.1",
    "typeorm": "^0.3.0",
    "pg": "^8.11.0"
  },
  "devDependencies": {
    "@nestjs/cli": "^10.0.0",
    "@nestjs/testing": "^10.0.0",
    "@types/jest": "^29.5.0",
    "@types/supertest": "^2.0.12",
    "jest": "^29.5.0",
    "supertest": "^6.3.0",
    "ts-jest": "^29.1.0"
  }
}

Deployment Best Practices

// main.ts - Production configuration
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  
  // Security
  app.enableCors();
  app.use(helmet());
  
  // Validation
  app.useGlobalPipes(new ValidationPipe({
    whitelist: true,
    transform: true,
  }));
  
  // Global exception filter
  app.useGlobalFilters(new AllExceptionsFilter());
  
  // API documentation
  if (process.env.NODE_ENV !== 'production') {
    const config = new DocumentBuilder()
      .setTitle('API Documentation')
      .setVersion('1.0')
      .addBearerAuth()
      .build();
    const document = SwaggerModule.createDocument(app, config);
    SwaggerModule.setup('api', app, document);
  }
  
  // Graceful shutdown
  process.on('SIGTERM', () => {
    console.log('SIGTERM received');
    app.close();
  });
  
  await app.listen(process.env.PORT || 3000);
}
bootstrap();

Key Interview Topics Summary

  1. Architecture: Modular design, dependency injection, decorators
  2. Request Lifecycle: Middleware → Guards → Interceptors → Pipes → Handler
  3. Database Integration: TypeORM patterns, repository usage, migrations
  4. Authentication: JWT strategies, guards, role-based access control
  5. Testing: Unit tests with mocking, integration tests, e2e testing
  6. Performance: Caching strategies, database optimization, async patterns
  7. Security: Input validation, rate limiting, security headers
  8. Microservices: Transport layers, message patterns, service communication
Found this useful? Pass it on.
Pro · $10/mo

The sheet is free. Pro goes deeper.

Pro opens the full question library behind every sheet, every refresher and a monthly AI allowance. One subscription, all formats.

Full question library All refreshers Cancel anytime