Technology handbook
Nest.js — APIs, Architecture, Security & Testing
Structured Node.js backend development with modules, providers, controllers, pipes, guards and testing.
- Topics
- 21
- Sections
- 6
Architecture
Modules
Group related controllers and providers into explicit dependency boundaries.
- Controllers and providers are grouped into explicit dependency boundaries.
- A provider is only injectable where its module is imported or it is exported.
- Circular imports between modules need forwardRef and usually a redesign.
Providers and dependency injection
Inject services through the container so business logic stays composable and testable.
- Services are injected through the container rather than constructed in place.
- Injection is what lets a test swap a real dependency for a fake.
- Scope is singleton by default, so per-request state in a provider is shared.
Dynamic modules
Configure reusable modules with forRoot, forFeature and asynchronous options.
- Reusable modules are configured through forRoot, forFeature and async options.
- forRoot configures once globally; forFeature configures per consumer.
- Async options exist so configuration can come from an injected service.
ModuleRef and lifecycle
Resolve providers dynamically and use module lifecycle hooks deliberately.
- Providers are resolved dynamically and lifecycle hooks used deliberately.
- It is the escape hatch when a dependency is only known at runtime.
- Resolving a scoped provider returns a new instance each time.
Queues and events
Move slow or retryable work to queues and decouple services with events.
- Slow or retryable work moves to queues and services decouple through events.
- Returning before the work finishes is what keeps the request fast.
- An in-process event emitter is lost on restart; a queue is not.
HTTP APIs
Controllers and routes
Map HTTP requests to typed handlers and keep transport concerns at the edge.
- HTTP requests map to typed handlers with transport concerns kept at the edge.
- Business logic in a controller cannot be reused by a queue consumer.
- Route order matters, so a wildcard declared early shadows what follows.
Interceptors and filters
Wrap execution for logging, response shaping and consistent exception handling.
- Interceptors wrap the handler on both sides of its execution.
- The post-request pass runs route, then controller, then global.
- Filters run last and convert a thrown error into a response.
Custom decorators
Extract request data or attach metadata without duplicating controller plumbing.
- Request data is extracted, or metadata attached, without repeating plumbing.
- A parameter decorator is what keeps the handler signature honest.
- Metadata decorators do nothing on their own; a guard must read them.
Serialization
Shape response payloads and hide internal fields with interceptors and serializers.
- Response payloads are shaped and internal fields hidden.
- Excluding a field in the entity is safer than remembering to omit it per route.
- The serializer only applies to class instances, not to plain objects.
OpenAPI documentation
Describe controllers, DTOs and authentication schemes for consumers and tooling.
- Controllers, DTOs and authentication schemes are described for consumers.
- The document is generated from the code, so it cannot drift from the routes.
- Types erased at compile time need explicit decorators to appear at all.
Request safety
Pipes and validation
Transform and validate untrusted route, query and body input before business logic runs.
- Pipes run after guards and interceptors, immediately before the handler.
- Route parameter pipes are evaluated last, in reverse parameter order.
- Validating here is what lets the handler trust its arguments.
DTOs and class-transformer
Transform transport input into explicit DTOs before validation and business logic.
- Transport input becomes an explicit object before validation or logic.
- A class is needed, not an interface, because the metadata must survive compilation.
- Transformation runs before validation, so a bad cast fails as a validation error.
ValidationPipe
Whitelist, transform and reject untrusted request data at the application boundary.
whitelist: true removes properties the DTO never declared.forbidNonWhitelisted: true rejects the request instead of silently stripping.- Both are options on the pipe rather than defaults.
Custom pipes
Convert route values and report precise validation failures with reusable pipes.
- Route values are converted and precise validation failures reported.
- One pipe replaces the same parsing repeated in every handler.
- Throwing inside a pipe is how the failure becomes a proper HTTP response.
Security
Guards and authentication
Decide whether a request may proceed before invoking the protected handler.
- A guard decides whether the request may reach the handler.
- Global, controller and route guards run in that order.
- It runs before pipes, so it sees untransformed input.
JWT authentication
Issue and verify access tokens while keeping secrets, expiry and claims controlled.
- Access tokens are issued and verified with secrets, expiry and claims controlled.
- A token cannot be revoked before expiry, so lifetimes must be short.
- Claims travel with the token, so they are as stale as the token is.
Role guards
Enforce role or permission policies before a controller handler runs.
- Role or permission policies are enforced before the handler runs.
- Roles are read from metadata, so the rule sits beside the route it protects.
- A guard registered globally still needs the route to declare what it requires.
Passport strategies
Integrate local, JWT and third-party authentication through named strategies.
- Local, JWT and third-party authentication integrate as named strategies.
- The strategy name is what links a guard to the mechanism it uses.
- A strategy's validate return becomes the request user, so its shape matters.
Testing
Testing controllers
Unit test handlers with mocked providers and assert transport behavior precisely.
- Handlers are unit tested with mocked providers and asserted precisely.
- A testing module builds the same container with substitutes in place.
- It exercises the handler, not the pipes and guards around it.
Testing e2e applications
Exercise a bootstrapped Nest application through real HTTP requests.
- A bootstrapped application is exercised through real HTTP requests.
- Only this path runs the pipes, guards and filters together.
- The application must be closed after each suite or handles leak.
Operations
Configuration module
Load and validate environment configuration without scattering process.env access.
- Environment configuration is loaded and validated in one place.
- Validating at boot turns a missing variable into a startup failure.
- Reading process.env directly scatters the contract across the codebase.