Global Modules

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

Global modules provide a set of providers that are available everywhere in the application without having to explicitly import the module.

Overview

If you have to import the same module (e.g., DatabaseModule, ConfigModule) everywhere, it can lead to a lot of boilerplate code in your imports arrays.

To solve this, NestJS provides the @Global() decorator. When a module is marked as global, the providers it exports become available to every other module in the application automatically.

Key Concepts

  • @Global() Decorator: Placed above the @Module() decorator.
  • Registration: A global module should be registered only once, typically in the root AppModule or a dedicated CoreModule.
  • Automatic Availability: Providers exported by a global module can be injected anywhere without needing to import the global module in the consuming feature module.

Code Examples

Defining a Global Module

import { Module, Global } from '@nestjs/common';
import { ConfigService } from './config.service';

// Mark the module as global
@Global()
@Module({
  providers: [ConfigService],
  // You still must export the providers you want to make globally available
  exports: [ConfigService], 
})
export class ConfigModule {}

Registering the Global Module

// app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule } from './config/config.module';
import { UsersModule } from './users/users.module';

@Module({
  // Register it once here
  imports: [ConfigModule, UsersModule],
})
export class AppModule {}

Consuming the Global Provider

// users.module.ts
import { Module } from '@nestjs/common';
import { UsersService } from './users.service';

@Module({
  // Notice we DO NOT import ConfigModule here
  providers: [UsersService],
})
export class UsersModule {}
// users.service.ts
import { Injectable } from '@nestjs/common';
import { ConfigService } from '../config/config.service';

@Injectable()
export class UsersService {
  // We can just inject it, and it works!
  constructor(private configService: ConfigService) {}
}

Best Practices

  • Use Sparingly: Making everything global is a bad design decision. It obscures dependencies and makes unit testing significantly harder because you have to guess which global providers a class secretly relies on.
  • Good Candidates for Global: Configuration (ConfigModule), Database Connections (TypeOrmModule.forRoot()), and global logging services.
  • CoreModule Pattern: A common pattern is to create a single global CoreModule that bundles and exports all global infrastructure (DB, Config, Logger) and import that CoreModule exactly once in AppModule.