Discover how to make your NestJS modules smart and adaptable with just a few lines of code!
Why Dynamic modules in NestJS? - Purpose & Use Cases
Imagine building a large NestJS app where you must manually import and configure every module for different environments or features.
You copy-paste similar code everywhere, changing only small details.
This manual setup is repetitive, error-prone, and hard to maintain.
Every time you add a new feature or environment, you risk breaking imports or configurations.
Dynamic modules let you create reusable, configurable modules that adjust their behavior based on input.
You write the setup once, then import it with different options easily.
import { Module } from '@nestjs/common'; @Module({ imports: [FeatureModule, AnotherModule], }) export class AppModule {}
import { Module } from '@nestjs/common'; @Module({}) export class DynamicFeatureModule { static forRoot(options: any) { return { module: DynamicFeatureModule, providers: [{ provide: 'CONFIG', useValue: options }], }; } }
Dynamic modules enable flexible, clean, and scalable app architecture that adapts easily to changing needs.
For example, you can create a database module that connects to different databases depending on environment variables without rewriting code.
Manual module setup is repetitive and fragile.
Dynamic modules allow configurable, reusable module patterns.
This leads to cleaner, more maintainable NestJS apps.
Practice
Solution
Step 1: Understand dynamic module concept
Dynamic modules let you pass custom options to configure the module when importing it.Step 2: Identify the main purpose
This flexibility helps reuse modules with different settings instead of hardcoding them.Final Answer:
To allow configuration of modules with custom options at runtime -> Option DQuick Check:
Dynamic modules = configurable modules [OK]
- Thinking dynamic modules remove controllers
- Believing dynamic modules auto-generate schemas
- Assuming dynamic modules have no providers
Solution
Step 1: Recall dynamic module pattern
Dynamic modules use a static method, commonly named forRoot, returning a DynamicModule object.Step 2: Match method signature
Only a static method can be called without creating an instance, fitting the dynamic module pattern.Final Answer:
static forRoot(options: ModuleOptions): DynamicModule { ... } -> Option BQuick Check:
Dynamic module method = static forRoot [OK]
- Using constructor instead of static method
- Defining dynamic module as a normal function
- Making dynamic module method async without returning DynamicModule
export class LoggerModule {
static forRoot(prefix: string): DynamicModule {
return {
module: LoggerModule,
providers: [
{ provide: 'LOGGER_PREFIX', useValue: prefix },
],
exports: ['LOGGER_PREFIX'],
};
}
}Solution
Step 1: Identify provider token
The provider uses the key 'provide' with value 'LOGGER_PREFIX' which is the token for injection.Step 2: Confirm exported token
The exports array includes 'LOGGER_PREFIX', so this token is available outside the module.Final Answer:
'LOGGER_PREFIX' -> Option CQuick Check:
Provider token = 'LOGGER_PREFIX' [OK]
- Confusing module name with provider token
- Using variable name 'prefix' as token
- Thinking useValue is the token
export class CacheModule {
static forRoot(options: { ttl: number }): DynamicModule {
return {
module: CacheModule,
providers: [
{ provide: 'CACHE_TTL', useFactory: (options) => options.ttl },
],
exports: ['CACHE_TTL'],
};
}
}Solution
Step 1: Analyze useFactory context
The useFactory function runs later and cannot directly access the outer options variable without injection.Step 2: Identify correct pattern
To use options inside useFactory, it must be passed via inject or closure properly; direct access causes runtime error.Final Answer:
The useFactory function cannot access options parameter directly -> Option AQuick Check:
useFactory needs inject or closure for options [OK]
- Thinking module property must be string
- Believing exports must list provider objects
- Assuming static methods can't return DynamicModule
Solution
Step 1: Understand dynamic module pattern for config
Dynamic modules use a static method (like forRoot) to accept config and return a DynamicModule object with providers.Step 2: Provide config and services properly
Use useValue or useFactory to inject config into providers, and export services to make them available outside.Final Answer:
Use a static forRoot method returning a DynamicModule with providers using useValue for config and export both services -> Option AQuick Check:
Dynamic module with static forRoot and providers = Use a static forRoot method returning a DynamicModule with providers using useValue for config and export both services [OK]
- Trying to configure modules via constructor
- Not exporting services after providing them
- Using global module without providers for config
Ready to prove it?
Pass the test and this pattern moves unknown
