--- title: Use Lazy Loading for Large Modules impact: MEDIUM impactDescription: Improves startup time for large applications tags: performance, lazy-loading, modules, optimization --- ## Use Lazy Loading for Large Modules NestJS supports lazy-loading modules, which defers initialization until first use. This is valuable for large applications where some features are rarely used, serverless deployments where cold start time matters, or when certain modules have heavy initialization costs. **Incorrect (loading everything eagerly):** ```typescript // Load everything eagerly in a large app @Module({ imports: [ UsersModule, OrdersModule, PaymentsModule, ReportsModule, // Heavy, rarely used AnalyticsModule, // Heavy, rarely used AdminModule, // Only admins use this LegacyModule, // Migration module, rarely used BulkImportModule, // Used once a month ], }) export class AppModule {} // All modules initialize at startup, even if never used // Slow cold starts in serverless // Memory wasted on unused modules ``` **Correct (lazy load rarely-used modules):** ```typescript // Use LazyModuleLoader for optional modules import { LazyModuleLoader } from '@nestjs/core'; @Injectable() export class ReportsService { constructor(private lazyModuleLoader: LazyModuleLoader) {} async generateReport(type: string): Promise { // Load module only when needed const { ReportsModule } = await import('./reports/reports.module'); const moduleRef = await this.lazyModuleLoader.load(() => ReportsModule); const reportsService = moduleRef.get(ReportsGeneratorService); return reportsService.generate(type); } } // Lazy load admin features with caching @Injectable() export class AdminService { private adminModule: ModuleRef | null = null; constructor(private lazyModuleLoader: LazyModuleLoader) {} private async getAdminModule(): Promise { if (!this.adminModule) { const { AdminModule } = await import('./admin/admin.module'); this.adminModule = await this.lazyModuleLoader.load(() => AdminModule); } return this.adminModule; } async runAdminTask(task: string): Promise { const moduleRef = await this.getAdminModule(); const taskRunner = moduleRef.get(AdminTaskRunner); await taskRunner.run(task); } } // Reusable lazy loader service @Injectable() export class ModuleLoaderService { private loadedModules = new Map(); constructor(private lazyModuleLoader: LazyModuleLoader) {} async load( key: string, importFn: () => Promise<{ default: Type } | Type>, ): Promise { if (!this.loadedModules.has(key)) { const module = await importFn(); const moduleType = 'default' in module ? module.default : module; const moduleRef = await this.lazyModuleLoader.load(() => moduleType); this.loadedModules.set(key, moduleRef); } return this.loadedModules.get(key)!; } } // Preload modules in background after startup @Injectable() export class ModulePreloader implements OnApplicationBootstrap { constructor(private lazyModuleLoader: LazyModuleLoader) {} async onApplicationBootstrap(): Promise { setTimeout(async () => { await this.preloadModule(() => import('./reports/reports.module')); }, 5000); // 5 seconds after startup } private async preloadModule(importFn: () => Promise): Promise { try { const module = await importFn(); const moduleType = module.default || Object.values(module)[0]; await this.lazyModuleLoader.load(() => moduleType); } catch (error) { console.warn('Failed to preload module', error); } } } ``` Reference: [NestJS Lazy Loading Modules](https://docs.nestjs.com/fundamentals/lazy-loading-modules)