A dynamic module returns a DynamicModule object from a static method (conventionally forRoot(), forFeature(), or register()) so the caller can pass configuration at import time. Use it for library modules like config, TypeORM, or mailer where behavior must vary per consumer.
Dynamic modules allow you to create customizable modules whose providers are determined at import time, based on options passed by the consuming module.
forRoot() — used once at the app level with global configuration.
forFeature() — used in feature modules with feature-specific config (e.g., TypeORM entities).
register() — general-purpose configuration, used in any module.