Modules

⭐ Interview Importance: MEDIUM
⏱️ Revision Time: 5 min

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.