DEV Community

Cover image for Graceful Shutdown in NestJS: Ensuring Smooth Application Termination
Hien Nguyen Minh
Hien Nguyen Minh

Posted on

Graceful Shutdown in NestJS: Ensuring Smooth Application Termination

A graceful shutdown is the process of shutting down a web application in a controlled and orderly manner, ensuring that all processes are safely terminated and all connections are closed. This is important for web applications as it helps to prevent data loss and corruption, and ensures that users are not left with incomplete or failed requests. In this blog post, we'll delve into the concept of graceful shutdown and learn how to implement it in a NestJS application.

Let's get started! 🐈

Why We Need Graceful Shutdown for the Server

Graceful shutdown is essential in scenarios like:

  • Deploying New Version: Ensure data integrity and user experience during version updates.

  • Scaling Operations: Avoid data inconsistencies when scaling up or down.

  • Zero Downtime: Maintain availability during updates.

  • Resource Cleanup: Properly release resources before shutdown.

  • Long-Running Processes: Allow ongoing tasks to complete before shutdown.

  • Background Tasks: Ensure background processes finish properly.

  • Server Failure: Handle shutdown during server failures to prevent data loss.

  • Enhancing User Experience: Maintain reliability and trust for users.

Implementing Graceful Shutdown for NestJS Application

To achieve a graceful shutdown in your application, you'll need to capture the shutdown signal and create a function that responds to it by performing tasks such as halting new requests, completing ongoing requests or tasks, and cleaning up resources. In the context of NestJS, you can utilize the enableShutdownHooks() method along with lifecycle events like onModuleDestroy, beforeApplicationShutdown, and onApplicationShutdown to handle the shutdown sequence effectively. These mechanisms allow you to respond to specific shutdown signals and execute actions like closing database connections and releasing resources as the application shuts down.

Here's a guide on how to implement this:

Consider the following code:

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

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.enableShutdownHooks(); // Enable listening for shutdown hooks

  await app.listen(3000);

  // For illustration purposes, delay the shutdown
  setTimeout(() => {
    process.kill(process.pid, 'SIGTERM');
  }, 5000);
}
bootstrap();

Enter fullscreen mode Exit fullscreen mode

If you have implemented a graceful shutdown for a NodeJS application or a specific NodeJS framework like ExpressJS, you may have noticed that you need to call the server.close() method from the native Node Server Instance to stop the server from accepting new connections while maintaining existing ones. However, It might lead to server hang indefinitely due to lingering keep-alive connections or unresponsive requests. This issue can also occur in NestJS applications using the enableShutdownHooks() method. To properly close the server, you must track the creation of all connections and terminate them yourself. To achieve this, you can use the nestjs-graceful-shutdown package available at npm, which simplifies the graceful shutdown process for your NestJS application.

Here's how you can integrate it:

  • Import the module into your root AppModule:
import { GracefulShutdownModule } from 'nestjs-graceful-shutdown';

@Module({
  imports: [
    GracefulShutdownModule.forRoot({
      cleanup: async (app) => {
        // releasing resources
        const myService = app.get(MyService);
        await myService.close();
      },
    })
  ],
  ...
})
class AppModule {}
Enter fullscreen mode Exit fullscreen mode
  • Set up graceful shutdown by calling the setupGracefulShutdown(...) function:
import { setupGracefulShutdown } from 'nestjs-graceful-shutdown';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  // Additional configuration for your NestJS app

  setupGracefulShutdown({ app });

  await app.listen(3000);

  // For illustration purposes, delay the shutdown
  setTimeout(() => {
    process.kill(process.pid, 'SIGTERM');
  }, 5000);
}
bootstrap();
Enter fullscreen mode Exit fullscreen mode

The nestjs-graceful-shutdown package also offers configuration options to manage resource cleanup before shutting down the server. Refer to the documentation for more details.

Conclusion

In conclusion, implementing a graceful shutdown in NestJS is crucial for ensuring a controlled and orderly shutdown process. By following these steps and utilizing the nestjs-graceful-shutdown package, you can seamlessly manage shutdown events and prevent disruptions during the shutdown process.

Happy hacking! 🐈

Top comments (2)

Collapse
 
micalevisk profile image
Micael Levi L. C.

you could also enable the forceCloseConnections option on NestFactory.create to avoid that behavior on keep-alive connections in the HTTP adapter.

Image description

Collapse
 
hienngm profile image
Hien Nguyen Minh • Edited

Thank you for your comment! I can also see that this option will forcefully close all connections, including ongoing ones. This is really useful for scenarios where we want to terminate keep-alive connections and are willing to accept that the server shutdown won't be graceful.