intermediate

NestJS modules

Organize features with modules, imports, exports, dynamic modules, shared providers, and explicit application boundaries.

Modules are NestJS composition units decorated with `@Module()`. They declare `controllers`, `providers`, `imports` (other modules), and `exports` (providers visible to importers). The root `AppModule` wires the application graph.

					@Module({
  imports: [DatabaseModule, UsersModule],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}
				

Feature modules encapsulate a bounded context. Shared modules export cross-cutting providers (config, logging). Dynamic modules (`forRoot`, `forRootAsync`) accept configuration at bootstrap — common for database and auth setup.

On interviews: explain module boundaries versus folder structure, what `exports` controls in the DI graph, and when to use global modules (`@Global()`) sparingly.

Common pitfalls: circular imports between modules, exporting everything globally, and god modules that own unrelated features.

The trade-off is balancing simplicity, performance, safety, and operability — name which axis you optimized and what cost you accepted.

Checklist:

  • One feature module per bounded context.
  • Export only providers other modules need.
  • Use dynamic modules for configurable infrastructure.
  • Resolve circular deps with `forwardRef` only when necessary.