In this article, I am going to show you how to do a graceful shutdown in NodeJS application, but first, let's describe what does means and why we need to do that in our application and what are the benefits. “graceful shutdown” Graceful shutdown Let’s imagine you have an HTTP server with NodeJS which connected to a database, and every time server gets called then it sends a request to the database to get/set a data which also will send to the client by the response. Imagine you need to shut down the server, the easiest way to do that is <Ctrl>+C and the server will be killed, but wait, what if your server did not finish all the requests, what if some client connections are closed because the server is killed and can not handle the requests. -That gives you a point to think, right? As you might guess you need to handle all requests and close all resources which are processing on data(e.e. database connections) and not take any other requests and after that, you can shut down your server with a quiet conscience. means when all your requests to the server is respond and not any data processing work left. Graceful shutdown It’s very important to create a graceful shutdown and shut down your server correctly because you can not know what can happen to the requests that have been made to the server if you shut down the server immediately, you can make mistake and kill the other process (byPID) which provided to the NodeJS server or some other things might happen, which could be bad for your application. How that works Here are the four steps of how you can do a graceful shutdown in an easy way. Handle process kill signal Stop new requests from client Close all data process Exit from process First of all we need to handle in the server that someone wants to shut down, after that we need to complete all the requests and stop taking new requests from users to the server, so we can be sure that there are no any pending requests from users to the server before shutting down the server, after that we need to close all the data processing (i.e. databases, some file system workers, etc..), it depends on what you are doing in the server, and finally we can exit from the process. Let’s create a simple NodeJS server and do all the steps that I have mentioned above which will do a graceful shutdown when we want to close the server and understand how it works. Here is a simple NodeJS Server example using ExpressJS express = ( ); mongoose = ( ); app = express(); app.use(express.urlencoded({extended: })); app.use(express.json()); mongoose.connect( , { (err) err; .log( ); }); User = mongoose.model( , { name: }); app.post( , (req, res) => { { user = User({ name: req.body.username }); user.save(); res.send( ).status( ); } (err) { res.send(err.message).status( ); } }); app.listen( , .log( )); const require 'express' const require 'mongoose' const true 'mongodb://localhost/test' ( ) => err if throw console 'Mongoose connected!' const 'User' String '/user' async try const new await 'Success!' 201 catch 500 3000 => () console 'Example app listening on port 3000!' Here we have a simple server which has a route that creates a user in MongoDB. We can test the server and create a user in the database using this command curl -d ‘{ “username”: “Narek” }’ -H “Content-Type: application/json” -X POST http: //localhost:3000/user If you got message then you can look the JSON data in MongoDB. Success! Now let’s go through the four steps and write appropriate code for that. 1. Handle process kill signal First, let’s understand what is a process signal. A is an asynchronous notification sent to a or to a specific thread to notify an event that occurred. signal process Signal events will be emitted when the NodeJS process receives a signal. Each signal have a name(i.e. 'SIGINT', 'SIGTERM', etc.), more about that in NodeJS . here 'SIGINT' generated with <Ctrl>+C in the terminal.The 'SIGTERM' signal is a generic signal used to cause program termination. Unlike 'SIGKILL' this signal can be blocked, handled, and ignored. It is the normal way to politely ask a program to terminate.The shell command kill generates 'SIGTERM' by default. You can read more about . Termination Signals here As you guess we need to add handler which will receive 'SIGTERM' signal. Here is the next example built on the previous example which handles the signal. express = ( ); mongoose = ( ); app = express(); app.use(express.urlencoded({ : })); app.use(express.json()); mongoose.connect( , (err) => { (err) err; .log( ); }); User = mongoose.model( , { : }); app.post( , (req, res) => { { user = User({ : req.body.username }); user.save(); res.send( ).status( ); } (err) { res.send(err.message).status( ); } }); app.listen( , () => .log( )); process.on( , () => { .info( ); }); const require 'express' const require 'mongoose' const extended true 'mongodb://localhost/test' if throw console 'Mongoose connected!' const 'User' name String '/user' async try const new name await 'Success!' 201 catch 500 3000 console 'Example app listening on port 3000!' 'SIGTERM' console 'SIGTERM signal received.' Now let’s try and test it. Run the server, after that you need to get PID number, you get that using ps command, so now you have the number and you can try to kill the server using this command kill [PID_number] or just killall node which will send a signal to all node servers, after running this command you will get this log from node outputs SIGTERM signal recived. If you will try again you will get the same log SIGTERM signal recived. -Hmmm, why the process has not been killed? Because you handled the signal and ignored it. So, the first step is done, let’s move to the next step. 2. Stop new requests from client Now we need to stop the http server and stop accepting new requests. It can be done using server.close function to get more information about that you can have a look also in . NodeJS doc So, the code will look like this express = ( ); mongoose = ( ); app = express(); app.use(express.urlencoded({ : })); app.use(express.json()); mongoose.connect( , (err) => { (err) err; .log( ); }); User = mongoose.model( , { : }); app.post( , (req, res) => { { user = User({ : req.body.username }); user.save(); res.send( ).status( ); } (err) { res.send(err.message).status( ); } }); server = app.listen( , () => .log( )); process.on( , () => { .info( ); .log( ); server.close( { .log( ); }); }); const require 'express' const require 'mongoose' const extended true 'mongodb://localhost/test' if throw console 'Mongoose connected!' const 'User' name String '/user' async try const new name await 'Success!' 201 catch 500 const 3000 console 'Example app listening on port 3000!' 'SIGTERM' console 'SIGTERM signal received.' console 'Closing http server.' => () console 'Http server closed.' It will stop accepting new connections to the server and if you will try to call the server your request will fail. 3. Close all data process In this example, the point is to close the MongoDB connection because not any requests left to the database. So it can be done with this code express = ( ); mongoose = ( ); app = express(); app.use(express.urlencoded({ : })); app.use(express.json()); mongoose.connect( , (err) => { (err) err; .log( ); }); User = mongoose.model( , { : }); app.post( , (req, res) => { { user = User({ : req.body.username }); user.save(); res.send( ).status( ); } (err) { res.send(err.message).status( ); } }); server = app.listen( , () => .log( )); process.on( , () => { .info( ); .log( ); server.close( { .log( ); mongoose.connection.close( , () => { .log( ); }); }); }); const require 'express' const require 'mongoose' const extended true 'mongodb://localhost/test' if throw console 'Mongoose connected!' const 'User' name String '/user' async try const new name await 'Success!' 201 catch 500 const 3000 console 'Example app listening on port 3000!' 'SIGTERM' console 'SIGTERM signal received.' console 'Closing http server.' => () console 'Http server closed.' // boolean means [force], see in mongoose doc false console 'MongoDb connection closed.' -Hmmmmmmm, why node server exits after DB connection close. It’s a very interesting question, you can try to understand that point by yourself, but if you can’t or don’t want I will describe it in the next chapter. 4. Close all data process As you have seen our application exits close database connection. -EventLoop What is the cause? As we know NodeJS will exit when EventLoop queue is empty and nothing left to do. But sometimes your application can have more functions and will not exit automatically, in this point comes our last work to do. We need to exit from process using process.exit function. And final graceful shutdown server example will look like this express = ( ); mongoose = ( ); app = express(); app.use(express.urlencoded({ : })); app.use(express.json()); mongoose.connect( , (err) => { (err) err; .log( ); }); User = mongoose.model( , { : }); app.post( , (req, res) => { { user = User({ : req.body.username }); user.save(); res.send( ).status( ); } (err) { res.send(err.message).status( ); } }); server = app.listen( , () => .log( )); process.on( , () => { .info( ); .log( ); server.close( { .log( ); mongoose.connection.close( , () => { .log( ); process.exit( ); }); }); }); const require 'express' const require 'mongoose' const extended true 'mongodb://localhost/test' if throw console 'Mongoose connected!' const 'User' name String '/user' async try const new name await 'Success!' 201 catch 500 const 3000 console 'Example app listening on port 3000!' 'SIGTERM' console 'SIGTERM signal received.' console 'Closing http server.' => () console 'Http server closed.' // boolean means [force], see in mongoose doc false console 'MongoDb connection closed.' 0 Argument 0 means exit with a code. To exit with a code use 1. “success” “failure” To get this exit code after shutdown, run this command in the terminal where you run your node server. echo $? By default NodeJS exits with process code 0 if EventLoop is empty. That’s it! Summary It’s not the only way to shutdown server correctly, this will work fine on small projects and can be written easily, but I am not saying in big projects, it’s not needed. In big projects more likely using server balancing (i.e. Nginx), you can balance the load and not send any request to that server and shutdown it. Thank you for reading this article, feel free to ask any questions or tweet me . @nairhar My article about “NodeJS Health Checks and Overload Protection” https://medium.com/@nairihar/nodejs-health-checks-and-overload-protection-368a132a725e