CodePark/ questions / Modules & architecture
START PRACTICINGPRACTICE
Backend question · NestJS › Modules & architecture

What is a dynamic module? Explain forRoot, forRootAsync, register and forFeature, and show how forRootAsync gets its options.

TypeOrmModule.forRootAsync({
  imports: [ConfigModule],
  inject: [ConfigService],
  useFactory: (config: ConfigService) => ({
    type: "postgres",
    url: config.get("DATABASE_URL"),
  }),
});

A dynamic module is a module whose providers are decided at runtime, not written as fixed metadata. A static method on the module returns a DynamicModule object. This object has module, providers, exports, and optionally imports and global. It extends the module's static metadata.

The method names follow a convention:

  • forRoot configures a module once for the whole app.
  • register configures it for one specific consumer. You can call it with different options in different places.
  • forFeature builds on a forRoot configuration for one feature module. For example, TypeOrmModule.forFeature([User]) registers repositories.

The Async variants, like forRootAsync, get their options from other providers, such as ConfigService. They accept useFactory together with inject and imports. They also accept useClass or useExisting. Nest runs the factory first, and the factory may be async. Only then does Nest create the module's providers.

For your own modules, ConfigurableModuleBuilder generates this boilerplate for you.

  • A static method returns a DynamicModule object.
  • forRoot is used once per app, register once per consumer and forFeature once per feature.
  • Async variants use useFactory with inject and imports.
  • This lets options depend on other providers, like ConfigService.
  • ConfigurableModuleBuilder generates the boilerplate.