Skip to main content

What is a controller in NestJS?

A Controller in NestJS is a class responsible for handling incoming requests and building responses for the client. Controllers are what define an API's endpoints (e.g. /users, /auth/login) and connect the outside world (HTTP, WebSocket, etc.) to the application's internal logic (services, repositories, etc.).

The core idea

A controller is the entry point of your backend application. It:

  • receives a request (HTTP, GraphQL, WebSocket);
  • extracts parameters, the body, headers, etc.;
  • calls services or other providers where the business logic lives;
  • returns a response to the client.

Controllers shouldn't contain complex business logic, they delegate that to services.

A simple controller example

javascript
import { Controller, Get, Post, Body, Param } from '@nestjs/common'; import { UsersService } from './users.service'; @Controller('users') // all routes start with /users export class UsersController { constructor(private readonly usersService: UsersService) {} @Get() // GET /users findAll() { return this.usersService.findAll(); } @Get(':id') // GET /users/:id findOne(@Param('id') id: string) { return this.usersService.findOne(id); } @Post() // POST /users create(@Body() body: { name: string; email: string }) { return this.usersService.create(body); } }

How the routes work

DecoratorHTTP methodExample URLDescription
@Get()GET/usersRetrieve data
@Post()POST/usersCreate a new record
@Put()PUT/users/:idFully update a record
@Patch()PATCH/users/:idPartially update a record
@Delete()DELETE/users/:idDelete a record

The main controller decorators

DecoratorPurpose
@Controller('path')Sets the base path for all of a controller's routes
@Get(), @Post(), @Put(), @Delete()Define the request type
@Param()Extracts parameters from the URL (/users/:id)
@Body()Extracts the request body (JSON)
@Query()Extracts query parameters (?page=2&limit=10)
@Headers()Access to the request headers
@Req() / @Res()Access to the request and response objects (Express/Fastify)
@HttpCode()Explicitly sets the response status
@UseGuards()Attaches guards (e.g. authentication)
@UseInterceptors()Intercepts and modifies the request/response

How a controller interacts with a service

A controller always reaches out to a service, to avoid duplicating business logic:

javascript
// users.service.ts @Injectable() export class UsersService { private users = [{ id: 1, name: 'John' }]; findAll() { return this.users; } findOne(id: string) { return this.users.find(u => u.id === +id); } create(user) { this.users.push({ id: Date.now(), ...user }); return user; } }

The key principles of controllers

  1. A controller is the routing layer. It determines which methods are called for specific URLs.
  2. Minimal logic. A controller shouldn't decide "what to do", only "who to hand it to".
  3. Dependency injection. A controller receives services through its constructor (constructor(private service: ServiceName)).
  4. Encapsulation. Each controller is usually tied to a specific module (e.g. UsersController inside UsersModule).

An example project structure with a controller

javascript
src/ ├── users/ │ ├── users.controller.ts ← the controller │ ├── users.service.ts ← the business logic │ └── users.module.ts ← ties both together └── app.module.ts

Summary

ConceptDescription
ControllerHandles requests and returns responses
RoleThe application's entry point, connecting the outside world to the logic
Main principleDelegates business logic to services
ToolsHTTP decorators, DI, Guards, Interceptors, Pipes

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.