Under The Hood
backend nestjs NestJS 10+

Dynamic Modules: forRoot(), forFeature(), and ConfigurableModuleBuilder

Last updated
Prerequisites:
NestJS Modules and Providers
TypeScript Generics and Factory Providers
  • nestjs
  • dynamic-modules
  • forRoot
  • forFeature
  • dependency-injection
  • architecture

Read at your depth

The practical view

Dynamic modules allow you to configure NestJS modules at runtime with custom options. Common conventions include `forRoot()` (configures a singleton module globally, like `DatabaseModule.forRoot({ url: '...' })`), `forFeature()` (registers specific entities/tokens within a domain module, like `TypeOrmModule.forFeature([User])`), and `forRootAsync()` (loads configuration asynchronously via `useFactory` and `ConfigService`). NestJS provides `ConfigurableModuleBuilder` to generate dynamic module boilerplate automatically.

The same idea in other frameworks

nestjs equivalent
`DatabaseModule.forRoot({ url })` returning `DynamicModule` with factory providers.

Legacy vs modern

Hardcoded Static Module vs ConfigurableModuleBuilder Dynamic Module

Hardcoded modules cannot receive dynamic options from `ConfigService`; dynamic modules allow runtime configuration injection.

before → after
Hardcoded Static Module
@Module({ providers: [{ provide: 'CONFIG', useValue: { host: 'localhost' } }] }) // ❌ Hardcoded configuration
ConfigurableModuleBuilder Dynamic Module
export class AuthModule extends ConfigurableModuleClass {} // ✅ NEW: Generates forRoot / forRootAsync automatically

Interview gotchas

Context

Interviewers test your knowledge of modular architecture conventions in enterprise NestJS apps.

The mechanical answer

`forRoot()` is meant to be called **once in the root `AppModule`** to configure a singleton infrastructure service globally (e.g. database connection pool, global JWT configuration). `forFeature()` is called in **domain feature modules** (e.g. `UsersModule`, `OrdersModule`) to register specific domain sub-resources (like repositories or message queues) that depend on the global connection configured by `forRoot()`.

Trap

Calling `forRoot()` in multiple child feature modules will create duplicate connection pools and multiple singleton instances, potentially leaking database connections.

Under The Hood — a multi-depth technical interview hub.

Third-party licenses Press ⌘ K to search.