In this technical blog post, we will explore different ways to terminate a Node.js application. While pressing ctrl-C in the console can close a program, we are more interested in discussing programmatically exiting.

Let’s start with the most drastic method, which should be avoided. The process core module provides a method called process.exit() that allows you to programmatically exit from a Node.js program. When this line is executed, the process is immediately forced to terminate. However, it is important to note that this abrupt termination can cause pending callbacks, ongoing network requests, filesystem access, and processes writing to stdout or stderr to be ungracefully terminated.

If immediate termination is acceptable, you can pass an integer to process.exit() to signal the operating system with an exit code. By default, the exit code is 0, indicating success. However, different exit codes can be used to communicate specific meanings to other programs in your system. More information on exit codes can be found at this link.

Alternatively, you can set the process.exitCode property to signal the desired exit code. When the program eventually ends, Node.js will return this exit code.

To gracefully exit a program, it should only terminate once all processing is completed. For example, when starting an HTTP server with Express, like the following:

const express = require('express');
const app = express();

app.get('/', (req, res) => {
    res.send('Hi!');
});

app.listen(3000, () => console.log('Server ready'));

This program will keep running indefinitely. If you were to call process.exit(), any pending or running requests would be abruptly aborted, which is not ideal.

To handle this situation, you need to send a SIGTERM signal to the program and handle it using the process signal handler. The SIGTERM signal is a signal that tells a process to gracefully terminate. It is commonly sent from process managers like upstart or supervisord, among others.

Here’s an example of how to handle the SIGTERM signal in the previous Express server program:

const express = require('express');
const app = express();

app.get('/', (req, res) => {
    res.send('Hi!');
});

const server = app.listen(3000, () => console.log('Server ready'));

process.on('SIGTERM', () => {
    server.close(() => {
        console.log('Process terminated');
    });
});

It is worth mentioning that signals are a POSIX intercommunication system used to notify processes of events. The SIGKILL signal tells a process to immediately terminate, similar to process.exit(). On the other hand, the SIGTERM signal instructs a process to gracefully terminate.

You can send the SIGTERM signal from inside the program or from another Node.js program or any other app running on your system that knows the process ID (PID) of the program you want to terminate. Here’s an example of how to send the SIGTERM signal from within the program:

process.kill(process.pid, 'SIGTERM');

By following these methods, you can ensure that your Node.js application exits gracefully, allowing for proper cleanup and handling of ongoing operations.