Running your Node & Express apps forever, no matter what, with Systemd and PM2

Running your Node & Express apps on your machine is easy. However, once you put them in production there are some new problems. What if the app crashes? What if the server restarts? What if some other failure happens?

We’ve already talked about deploying on Ubuntu and CentOS but today we are going to go a little bit more specific.

You need your apps to be running forever, no matter what happens. Unfortunately applications crash in unexpected ways and servers restart due to bugs or power or hardware failures. In all cases, you need to ensure that your app can return to operating normally, all by itself.

You don’t want to wake up in the middle of the night or to cut your vacation short because your web app stopped working.

An application that automatically keeps itself always running, even in the events of bugs or system restarts, gives you peace of mind and allows you to investigate the problem when you find it convenient, instead at 4 in the morning.

Systemd

Fortunately, all modern Linux distributions come with a very powerful, but easy to use service called systemd. It can do many things (and many people argue whether it should do so many), but in our case we would look at how it will keep your application always alive.

All you have to do is to create the following file /etc/systemd/system/node-5000.service with the content below

[Service]
ExecStart=/usr/bin/node /opt/app/app.js

Restart=always

StandardOutput=syslog

StandardError=syslog

SyslogIdentifier=node-app-1

User=your_app_user_name

Group=your_app_user_name

Environment=NODE_ENV=production PORT=5000


[Install]
WantedBy=multi-user.target

This is called a service by systemd. Of course replace your_app_user_name with whatever is appropriate for your case.

The service above runs your app from /opt/app/app.js and sets two environment variables NODE_ENV and PORT which your app can use to configure itself.

To start your service do the following

$ systemctl start node-5000

Even if your app crashes it will be automatically restarted.

When you have some new code ready to run, all you have to do is

$ systemctl restart node-5000

There is one more thing to do to make sure that your app will be running forever

$ systemctl enable node-5000

After this command your app will start when the server starts. So when it is restarted for some reason, like power outage or some hardware failure it will still run.

Let’s look at some other useful commands.

$ systemctl status node-5000 

Will give you the current status of your service as well as other useful information.

$ systemctl stop node-5000

Will stop your service.

$ systemctl disable node-5000

Will prevent the service from starting at server startup.

Cores & Processors

Most modern servers have many CPUs and each has multiple cores. At the same time Node is famously a single process. So with the setup above you are not using all your available resources.

All you have to do to use your other resources is take the service definition from above and change everywhere you see 5000 (including the file name) to some other port like 5001 :-).

Like this you can run as many instances of your app, one for each core on each CPU.

Of course you will need some load balancer, like Nginx in front so that it can direct the web traffic to your app instances.

In all cases you will need nginx or something similar to serve your static files so this is not a big addition.

Disadvantages

However, this is not a very elegant solution, and you have to manually setup everything. If you change your server to one with more processing power, again you will have to manually create more services.

Another problem is when you update your app, you will have to manually restart each service. Even when you write a script to do this for you for all services it is still not trivial to ensure 0 downtime. You don’t want all your instances restarting at the same time.

PM2

Systemd is great but thanks to PM2, we can make this even better. PM2 is a process manager written specifically for Node apps and works perfectly with Express.

All you have to do to install it is

$ npm install pm2 -g

Yes, we install this NPM module globally because we want to easily control it and it is not specific to our Node app.

Then all you have to do is

$ pm2 start app.js -i max

This will keep your app running forever and it will also create as many instances as cores your server has. The result will be that you will use your resources in an optimal way.

Once your application is running all you have to do to stop it is

$ pm2 stop app.js

When there is new code again it is very simple

$ pm2 reload app.js

This will not only reload your code and replace it with your update version, but it will also do it with zero down time for your users. It will reload each of your app instances one by one.

PM2 and Systemd

The next problem we face is that when the server restart pm2 will not start and your application will not start. To fix this pm2 comes with a very handful command which can generate a systemd service. It is just one line

$ pm2 startup systemd

It will generate a service to restart pm2 and will put it where it belongs. Once you run your app with pm2 start app.js -i max it will always be on and it will run your app even when the server restarts.

You can learn even more useful PM2 commands from https://github.com/Unitech/pm2

Where to go from here?

Today I showed you how to run your Node & Express process forever, but there is more to deploying a web app. Read our articles form the links below, on how to deploy your Node app on Ubuntu or CentOS from start to finish.


Other articles that you may like

Did you like this article?

Please share it

We are Stefan Fidanov & Vasil Lyutskanov. We share actionable advice about development with Node, Express, React and other web & mobile technologies.

It is everything that we have learned from years of experience working with customers from all over the world on projects of all sizes.

Let's work together
© 2024 Terlici Ltd · Terms · Privacy