Turbocharge Your App with NestJS - Tips and Tricks

Turbocharge Your App with NestJS - Tips and Tricks

Sunny Sun lol

4 Performance Boosting Techniques to Get the Most Out of NestJS

As a powerful Node.js application framework, NestJS offers a wide range of features for building server-side apps. Its popularity continues to grow as more developers discover its benefits.

However, when it comes to building a NestJS app, performance is often an overlooked aspect. In this article, I will discuss a few practical techniques for crafting a high-performance NestJS application

Architecture Choice

By default, NestJS runs on top of Express primary due to its popularity. Although there are some overheads, NestJS’s performance isn’t far away from Express. Express is considered to be a well-performed framework. Thus the default option: Nest-Express is good enough for a normal server-side App.

But if performance is the first priority, a better option is to use Fastify which is much faster than Express.

Below is a recent benchmark test results for Nest-Express vs Nest-Fastify vs Express alone. We can see that Nest-Fastify is more than 3 times faster than Nest-Express.

A recent benchmark ([https://github.com/nestjs/nest/pull/10276/checks?check_run_id=8318006381](https://github.com/nestjs/nest/pull/10276/checks?check_run_id=8318006381))A recent benchmark (https://github.com/nestjs/nest/pull/10276/checks?check_run_id=8318006381 )

If you are building a new NestJS App, one of the first things to consider is whether you should stick to the Express, or start with Fastify. For existing Apps, it is also possible to migrate to Fastify from Express since Nest provides framework independence using adapter .

Caching

Caching can improve your NestJS app or any web app performance dramatically. It is a complex topic and is considered to be one of the two hard things in computing . However, NestJS has made it easier with its well-abstracted API.

NestJS provides an out-of-box cache manager. The cache manager provides an API for various cache storage providers. The default storage provider is an in-memory data store and it is built-in. To enable in-memory caching, we need to import the CacheModule as below.

import { CacheModule, Module } from '@nestjs/common';
import { AppController } from './app.controller';

@Module({
  imports: [CacheModule.register()],
  controllers: [AppController],
})
export class AppModule {}

For more configuration options, refer to the official documentation .

You can switch to a number of other storage providers, for example, redis store .

Regardless of which storage provider you choose, you can set up a cache interceptor to automatically cache the get response.

import * as redisStore from 'cache-manager-redis-store';
@Module({
  imports: [CacheModule.register({store: redisStore})],
  controllers: [AppController],
  providers: [
    {
      provide: APP_INTERCEPTOR,
      useClass: CacheInterceptor,
    },
  ],
})

The above configuration will import CacheInterceptor, and bind it to all endpoints globally. Alternatively, you also can use UseInterceptors to bind the CacheInterceptor at the controller level.

Enable Gzip

Enabling Gzip compression can greatly improve API performance. It doesn’t only work with NestJS, instead, it is applicable to any common Web API service. It is easy to implement and very effective, but at the same time also easily to be forgotten.

Gzip compresses API requests and responses. The result is up to 10x reduced payload.

You can either enable Gzip compression via Nginx. Most NestJS apps sit behind Nginx, and you can configure Nginx to use gzip to compress the HTTP response on the fly. The following is an example to enable Gzip in nginx.conf.

gzip on;
gzip_disable "msie6";

Another way is to enable Gzip within the NestJS app. In your NestJs App, you can make use of the compression middleware package provided to compress and serve content.

import * as compression from 'compression';
// somewhere in your initialization file
app.use(compression());

In the above example, the compression middleware is imported from the @nestjs/common package and used to enable gzip compression for all requests to the app. This allows the app to compress the response using gzip if the client supports it, which can improve the performance and efficiency of the app.

Cluster Mode

By default, the NestJS App instance runs in a single thread. Since all servers have multiple CPU cores, the single-thread instance doesn’t take full advantage of the server resources.

To utilize the multiple cores to improve performance, we can use the Cluster module in NodeJS. Under cluster mode, the child processes run as a cluster, thus incoming requests are handled simultaneously. It results in better throughput.

It is straightforward to create a cluster service in NestJS. Below is an example of implementation.


import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import * as os from 'os';

const cluster = require('node:cluster');
const numCPUs = os.cpus().length;

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);
}
if(cluster.isMaster){
  console.log(`Master server started on ${process.pid}`);
  for (let i = 0; i < numCPUs; i++) {
      cluster.fork();
  }
  cluster.on('exit', (worker, code, signal) => {
      console.log(`Worker ${worker.process.pid} died. Restarting`);
      cluster.fork();
  })
} else {
  console.log(`Cluster server started on ${process.pid}`)
  bootstrap();
}

The gist of the above code is

  • Firstly, we import the cluster module and get the number of CPU cores

  • The master process is responsible for creating the worker processes, and the worker processes are responsible for running the NestJS app.

  • For the master process, a worker process is created for each CPU available. We also listen to the exit of a worker process, when any worker process crashes, the master process will fork a new one.

  • For the child process, we can use the bootstrap function to start the server instance.

In the production environment, you can use pm2 to run the App in cluster mode. The command below will start the app with cluster mode for 8 CPU cores.

pm2 start dist/main.js -i 8

Overall, using cluster mode in a NestJS app can provide improved performance and scalability by sharing the workload across multiple worker processes.

Summary

Optimizing the performance of a NestJS application is a complex and multifaceted task. In this article, we discussed how to utilize the built-in NestJS features like Fastify, and Cache Manager to improve performance. Gzip and Cluster modules are also commonly used to optimize not only NestJS but also other NodeJS web apps.

If you found this article useful, you may also like to check out my other NestJS-related articles on how to build efficient and maintainable NestJS apps and NestJS security .

Happy programming!