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
| Decorator | HTTP method | Example URL | Description |
|---|---|---|---|
@Get() | GET | /users | Retrieve data |
@Post() | POST | /users | Create a new record |
@Put() | PUT | /users/:id | Fully update a record |
@Patch() | PATCH | /users/:id | Partially update a record |
@Delete() | DELETE | /users/:id | Delete a record |
The main controller decorators
| Decorator | Purpose |
|---|---|
@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
- A controller is the routing layer. It determines which methods are called for specific URLs.
- Minimal logic. A controller shouldn't decide "what to do", only "who to hand it to".
- Dependency injection.
A controller receives services through its constructor (
constructor(private service: ServiceName)). - Encapsulation.
Each controller is usually tied to a specific module (e.g.
UsersControllerinsideUsersModule).
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.tsSummary
| Concept | Description |
|---|---|
| Controller | Handles requests and returns responses |
| Role | The application's entry point, connecting the outside world to the logic |
| Main principle | Delegates business logic to services |
| Tools | HTTP decorators, DI, Guards, Interceptors, Pipes |
Short Answer
Interview readyPremium
A concise answer to help you respond confidently on this topic during an interview.