Lazy Loading in NestJS: Boosting Performance and Efficiency

Abdelrahman Rezk
3 min readMay 26, 2024

--

Lazy loading is a powerful design pattern that delays the initialization of resources until they are actually needed. This can significantly enhance the performance and resource management of your application. In NestJS, lazy loading can be implemented using dynamic modules and the LazyModuleLoader from @nestjs/core. This article explores both methods, providing detailed examples to help you implement lazy loading in your NestJS applications.

Why Lazy Loading?

Lazy loading helps in:

  1. Reducing Initial Load Time: By not loading everything at startup, the application can start faster.
  2. Optimizing Resource Usage: Only load the components or modules when they are actually needed.
  3. Improving Scalability: Efficient use of resources can help the application scale better.

Using LazyModuleLoader for Lazy Loading

To implement lazy loading in NestJS we useLazyModuleLoader from @nestjs/core.

Step 1: Create the Module to be Lazy Loaded

Create the ReportsModule similarly as before.

// reports.module.ts
import { Module } from '@nestjs/common';
import { ReportsService } from './reports.service';
import { ReportsController } from './reports.controller';

@Module({
controllers: [ReportsController],
providers: [ReportsService],
})
export class ReportsModule {}

Step 2: Create the Service for the Lazy Loaded Module

Define the service for the ReportsModule.

// reports.service.ts
import { Injectable } from '@nestjs/common';

@Injectable()
export class ReportsService {
getReport(): string {
console.log('lazily loaded reports module');
return 'This is a report!';
}
}

Step 3: Define the Main Module

Define the AppModule without importing ReportsModule as we will import it later lazilly.

// app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
imports: [],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}

Step 4: Create a Controller to Handle Lazy Loading and Other Logic

Create a controller that uses LazyModuleLoader to load the ReportsModule dynamically.

// app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { LazyModuleLoader } from '@nestjs/core';
import { ReportsModule } from './reports/reports.module';
import { ReportsService } from './reports/reports.service';

@Controller()
export class AppController {
constructor(private readonly lazyModuleLoader: LazyModuleLoader) {}

@Get()
async getLazyReport(): Promise<string> {
// use console.time() and console.timeEnd()
//to get the initialization time of ReportsModule
console.time();
const moduleRef = await this.lazyModuleLoader.load(() => ReportsModule);
const reportsService = moduleRef.get(ReportsService);
console.timeEnd();
return reportsService.getReport();
}
}

Example Usage

When the first request is made to the endpoint, the ReportsModule will be loaded lazily, and the ReportsService will handle the request, returning a report.

$ curl http://localhost:3000/lazy-reports
This is a report!

And if you made more requests each consecutive attempt to load ReportsModule is much faster the load method returns a cached instance of the module.

Making more than one request you will see output like this in app logs.

default: 6.226ms
lazily loaded reports module
[Nest] 208649 - 05/26/2024, 8:33:22 PM LOG [LazyModuleLoader] ReportsModule dependencies initialized
default: 2.323ms
lazily loaded reports module
[Nest] 208649 - 05/26/2024, 8:33:22 PM LOG [LazyModuleLoader] ReportsModule dependencies initialized
default: 2.012ms
lazily loaded reports module

Conclusion

Implementing lazy loading in NestJS can significantly enhance the performance and resource efficiency of your application.

Using LazyModuleLoader in NestJS ensures that modules are loaded lazily once for first time and cached, optimizing performance and resource usage. This approach helps manage dynamic module loading efficiently, providing a balance between initial load time and runtime efficiency.

--

--