Guards control who can access parts of your app. Binding levels decide where guards apply: globally, to a whole controller, or just one route.
Guard binding levels in NestJS
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; @Injectable() export class MyGuard implements CanActivate { canActivate(context: ExecutionContext): boolean { // your logic here return true; } } // Global binding app.useGlobalGuards(new MyGuard()); // Controller binding @UseGuards(MyGuard) @Controller('cats') export class CatsController {} // Route binding @UseGuards(MyGuard) @Get() findAll() {}
Global guards run for every request in the app.
Controller guards run for all routes inside that controller.
// Global guard binding app.useGlobalGuards(new MyGuard());
@UseGuards(MyGuard) @Controller('users') export class UsersController {}
@UseGuards(MyGuard)
@Get('profile')
getProfile() {}This example shows a guard applied at the controller level. It only allows access if the URL query has ?allow=true. Both routes in HelloController are protected by this guard.
import { Controller, Get, Injectable, CanActivate, ExecutionContext, UseGuards } from '@nestjs/common'; import { NestFactory } from '@nestjs/core'; import { Module } from '@nestjs/common'; @Injectable() class SimpleGuard implements CanActivate { canActivate(context: ExecutionContext): boolean { const request = context.switchToHttp().getRequest(); // Allow only if query param 'allow' is 'true' return request.query.allow === 'true'; } } @Controller('hello') @UseGuards(SimpleGuard) // Controller level guard class HelloController { @Get() sayHello() { return 'Hello World'; } @Get('open') openRoute() { return 'Open Route'; } } @Module({ controllers: [HelloController], providers: [SimpleGuard], }) class AppModule {} async function bootstrap() { const app = await NestFactory.create(AppModule); await app.listen(3000); } bootstrap();
Guards run before route handlers to decide if the request can continue.
Use global guards for app-wide rules like authentication.
Use controller or route guards for more specific access control.
Guards can be bound globally, to controllers, or to individual routes.
Global guards protect every request in the app.
Controller and route guards let you control access more precisely.
Practice
Solution
Step 1: Understand global guard scope
Global guards are set once and protect every request in the app.Step 2: Compare with other guard levels
Route guards apply only to specific routes, and controller guards apply to all routes in a controller. Route guards can override controller guards.Final Answer:
Global guards apply to all routes in the application. -> Option BQuick Check:
Global guard = all routes [OK]
- Thinking route guards apply globally
- Believing controller guards cannot be overridden
- Assuming guards can't be applied to routes
Solution
Step 1: Identify route-level guard binding
To bind a guard to a specific route, place @UseGuards() decorator above the route handler method.Step 2: Differentiate from other bindings
@UseGuards() above the controller binds to all routes in that controller. Global guards are set differently, and @GlobalGuard does not exist.Final Answer:
@UseGuards(MyGuard) above the route handler method -> Option DQuick Check:
Route guard = @UseGuards on method [OK]
- Putting @UseGuards only on controller for route guard
- Confusing global providers with route guards
- Using non-existent @GlobalGuard decorator
GET /users/profile route?@UseGuards(GlobalGuard)
@Controller('users')
@UseGuards(ControllerGuard)
export class UserController {
@Get('profile')
@UseGuards(RouteGuard)
getProfile() {
return 'User Profile';
}
}Solution
Step 1: Identify guard binding levels in code
GlobalGuard is bound globally, ControllerGuard on the controller, and RouteGuard on the route method.Step 2: Understand guard execution order
All guards bound at different levels run in order: global first, then controller, then route.Final Answer:
GlobalGuard, ControllerGuard, and RouteGuard all run in order. -> Option AQuick Check:
All guards run in binding order [OK]
- Assuming only one guard runs
- Thinking controller guard disables others
- Believing global guard runs alone
Solution
Step 1: Check guard binding syntax
Controller guards must be explicitly added with @UseGuards on the controller class.Step 2: Understand guard coexistence
Global and controller guards can coexist; global guards do not block controller guards from running.Final Answer:
The controller guard was not added to the controller with @UseGuards. -> Option AQuick Check:
Missing @UseGuards on controller = no controller guard [OK]
- Thinking global guard blocks controller guards
- Believing guards can't be combined
- Forgetting to decorate controller with @UseGuards
Solution
Step 1: Understand guard override behavior
Controller-level guards apply to all routes in that controller but can be overridden by route-level guards.Step 2: Apply guard to block all except one route
Binding the guard on the controller blocks all routes; then a route-level guard on the exception route can allow access.Final Answer:
Bind the guard on the controller and override it with a route-level guard that allows the exception. -> Option CQuick Check:
Controller guard + route override = selective access [OK]
- Trying to remove global guards per route (not supported)
- Binding guard only on exception route (wrong logic)
- Assuming global guard can be skipped per route
Ready to prove it?
Pass the test and this pattern moves unknown
