What it is
NestJS is a structured Node.js framework built on TypeScript decorators, with dependency injection, modules and a strong architectural convention.
Applications are composed of modules containing controllers and providers. Dependencies are injected by type, and cross-cutting concerns are handled by guards, interceptors, pipes and filters.
Installation
npm i -g @nestjs/cli && nest new projectGetting started
The smallest useful thing you can do with it, and what each part means.
@Injectable()
export class BooksService {
constructor(private readonly repo: BookRepository) {}
findOne(id: string) { return this.repo.findById(id); }
}
@Controller('books')
export class BooksController {
constructor(private readonly books: BooksService) {}
@Get(':id')
async findOne(@Param('id') id: string) {
const book = await this.books.findOne(id);
if (!book) throw new NotFoundException(`Book ${id} not found`);
return book;
}
}
@Module({
controllers: [BooksController],
providers: [BooksService, BookRepository],
})
export class BooksModule {}export class CreateBookDto {
@IsString() @MaxLength(200)
title: string;
@IsInt() @Min(1400)
year: number;
}
// main.ts — apply globally
app.useGlobalPipes(new ValidationPipe({
whitelist: true, // strip unknown properties
forbidNonWhitelisted: true, // or reject them outright
transform: true, // turn plain objects into DTO instances
}));Advanced usage
Where the library earns its place over a simpler alternative.
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
const required = this.reflector.get<string[]>('roles', context.getHandler());
if (!required) return true;
const { user } = context.switchToHttp().getRequest();
return required.some((role) => user?.roles?.includes(role));
}
}
@Injectable()
export class TimingInterceptor implements NestInterceptor {
intercept(ctx: ExecutionContext, next: CallHandler) {
const started = Date.now();
return next.handle().pipe(
tap(() => Logger.log(`${ctx.getHandler().name} ${Date.now() - started}ms`)),
);
}
}Errors and fixes
The failures you are most likely to hit, and what actually resolves them.
- Nest can't resolve dependencies of the X
- The provider is not in the module's providers array, or its module does not export it. The error names the missing parameter index.
- Validation decorators are ignored
- ValidationPipe is not registered, or the DTO is an interface. Decorators need a real class — interfaces are erased.
Best practices
- Enable ValidationPipe with whitelist and forbidNonWhitelisted globally, or unknown fields flow through.
- Keep controllers thin — they should translate HTTP to a service call and back.
- Use the built-in HTTP exceptions so status codes stay consistent.
- Choose Nest when the team wants enforced structure; it is heavy for a small API.
Background
Why it exists, and what it was reacting to.
Created by Kamil Myśliwiec and modelled on Angular's architecture, NestJS brought Spring-style structure to Node — appealing to teams from Java or C# backgrounds who found Express too unopinionated for large applications.
