You want to launch your Node.js application. Perhaps this is your first time. The app is a backend API, and it's ready to face the public.
How do you properly start a Node.js application in production? What are the best practices, and how is it different from development?
Don't let doubt stop you.
Confidently launch a Node.js server that's always available to respond to incoming requests, just like you programmed it.
Start your application like the rest of the Node.js community — by using a process manager. Choose from three most popular process managers based on your situation and needs.
Foreground vs background processes
During development, you're probably used to starting your Node.js server by opening up the terminal and typing
node index.js, or whatever file is the starting point of your application. If this command lives in the package.json file, you run it through NPM with
When you press CTRL+C or close the terminal, the application exits as well. That's usually what we want during development. In a production environment, however, an application should keep running beyond the lifecycle of our terminal or SSH connection.
When you work on an application locally, you start it as a foreground process. In the foreground, your keyboard input is directed to the process. That's why when you hit CTRL+C, it sends a
SIGINT signal and stops the application.
What we want instead is to start the application in the background. To start an application in the background, you simply append
& at the end of the command. From the previous example,
node index.js & will start your Node.js server in the background which will stay up even after you close the terminal or SSH connection to your production server.
What happens if your application crashes?
With your application now running independently, what happens if it crashes or stops responding? Applications inevitably crash in production due to one of many reasons — a memory leak that leads to an out-of-memory exception, a rejected promise isn't caught in the code, unexpected user input causes an infinite loop, and so on.
To solve this, we would need another process that manages our application and is responsible for restarting it on such occasions. That's exactly what process managers do.
A process manager starts your application as a background process and will restart it when it crashes. It can also automatically start your application on system startup if you want. Keeping your application alive is by far the most important feature of process managers.
The three most used process managers by Node.js developers are PM2, Docker and Systemd. Depending on your situation and purpose, you might be better off using one over the other. All three, however, are used by many applications in production, and you can't go wrong with either of them.
Process managers for Node.js applications
The official documentation is always a good place to start when you want to learn about a library or tool. To get started with PM2, I recommend following their quick start guide.
When I'm deploying an application that doesn't live in a container, PM2 is my go-to process manager. It's easy to use and allows me to focus on building features.
If you're using Docker to containerise and deploy your application, you can use the built-in process management features. With the Docker CLI, you can manage your application container and configure it to automatically restart your application if it crashes.
You can also define a
HEALTHCHECK in your Dockerfile. Docker will then use it to determine if your application is healthy. Health checks are useful when your application could be running, but unable to handle new requests because it's stuck in an infinite loop.
When I'm deploying a Node.js application with Docker, I don't use PM2 as most of its benefits are replaced by Docker.
Every operating system comes with a process manager by default. For the most popular Linux distributions, that's systemd. You can look at systemd as the "root" process manager. If you're using a process manager such as PM2 or Docker, they themselves are managed by systemd. Systemd is the first process started by the Linux kernel on system startup, and it's in charge of starting all other processes.
Systemd is a bit daunting to learn if you're unfamiliar with systems administration. However, it's a great way to start learning about DevOps and getting more comfortable using Linux. This old, but still relevant, article shows you how to use systemd with Node.js.
We've talked about the difference between running a process in the foreground and background. In production environments, we want our applications to keep running after we close the terminal, so we start them in the background.
Applications will inevitably crash, and a process manager makes sure to restart them when they do. They keep your application alive, and they can automatically start the application on system startup.
PM2 is the most used process manager in the Node.js community and is easy to use. Docker has built-in process management features, so if your application lives in a container, you can make use of them. If you want to learn about the world of DevOps and want to be more comfortable with Linux, using systemd is great for learning.
There's more to running Node.js in production besides automatic restarts. You have to add useful logs, think about monitoring, alerting and a whole plethora of other things. You don't have to learn them all at once, and tackling each topic individually, is a good way to improve your skills and confidence over your production deployments.
I prefer the learn-as-you-go style of learning. Focus on getting your application live and show the world what you've built. Worry about the rest later. Tools are a means to an end, and never the goal.