Modules
Modules are the fundamental building blocks used to organize a NestJS application’s structure and group related capabilities.
Overview
A module is a class annotated with a @Module() decorator. The @Module() decorator provides metadata that Nest makes use of to organize the application structure. Every Nest application has at least one module, known as the root module (usually AppModule), which acts as the starting point for resolving the application and dependency graph.
While smaller applications might only have one module, it is a best practice to organize your application into multiple feature modules (e.g., UsersModule, AuthModule, OrdersModule).
Key Concepts
- providers: The providers (e.g., services, repositories) that will be instantiated by the Nest injector and that may be shared at least across this module.
- controllers: The set of controllers defined in this module which have to be instantiated.
- imports: The list of imported modules that export the providers which are required in this module.
- exports: The subset of providers that are provided by this module and should be available in other modules which import this module.
Code Examples
A Standard Feature Module
import { Module } from '@nestjs/common';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
@Module({
// Other modules required by this module
imports: [DatabaseModule],
// Controllers to be instantiated
controllers: [UsersController],
// Services/Providers to be instantiated and injected
providers: [UsersService],
// Services to make available to OTHER modules that import UsersModule
exports: [UsersService]
})
export class UsersModule {}
The Root Module (app.module.ts)
import { Module } from '@nestjs/common';
import { UsersModule } from './users/users.module';
import { AuthModule } from './auth/auth.module';
@Module({
imports: [UsersModule, AuthModule],
})
export class AppModule {}
Global Modules
If you have a module that needs to be available everywhere (like a Database connection or Configuration service), you can use the @Global() decorator. Global modules should be registered only once, generally in the root module.
import { Module, Global } from '@nestjs/common';
import { ConfigService } from './config.service';
@Global()
@Module({
providers: [ConfigService],
exports: [ConfigService],
})
export class ConfigModule {}
Best Practices
- Feature-based Organization: Group your files by feature (e.g.,
users/users.controller.ts,users/users.service.ts,users/users.module.ts) rather than strictly by file type. - Avoid Circular Dependencies: Be careful when Module A imports Module B, and Module B imports Module A. If unavoidable, use
forwardRef(), but ideally refactor your architecture to extract shared logic into a third module. - Use Global Modules Sparingly: Don’t make every module global just to avoid importing them. Explicit imports make dependency graphs predictable and easier to test.