Automation & DevOps

PM2 vs systemd for keeping a Node.js app alive on a VPS

Both will restart your Node app when it crashes. The real differences show up in log handling, zero-downtime reloads, cluster mode, and how much you want to depend on a Node-specific tool versus what's already built into Linux.

V Vinod Kulkarni
19 August 2026 · 8 min read
PM2 vs systemd for keeping a Node.js app alive on a VPS

PM2 vs systemd for keeping a Node.js app alive on a VPS

TL;DR: systemd is already installed on essentially every modern Linux VPS and gives you solid process supervision, automatic restart, and boot-time startup with no additional software to install or maintain, but its logging and zero-downtime reload story is more manual to set up well. PM2 is a Node-specific process manager that adds cluster mode (running multiple instances across CPU cores with load balancing built in), simpler log management out of the box, and zero-downtime reloads with a single command, at the cost of one more piece of software in your stack that itself needs to stay running and occasionally gets updated.

What each one actually is

systemd is the Linux init system and service manager present by default on essentially every current major distribution (Ubuntu, Debian, and most others you would deploy a VPS with). It manages system services generally, not anything specific to Node.js, and running a Node app under it means writing a unit file that tells systemd how to start your app, treating it as one more managed service alongside everything else the OS runs.

PM2 is a separate, third-party process manager built specifically for Node.js applications. It runs as its own daemon process, itself needs to be started (commonly configured to run under systemd for its own persistence, an important detail covered below), and provides a purpose-built set of features on top of basic process supervision: application-aware log management, built-in cluster mode for Node specifically, a startup-script generator, and a monitoring dashboard.

Where systemd wins

No additional dependency. Since systemd is already present and already the thing supervising every other service on your VPS, using it for your Node app too means one consistent supervision mechanism for your entire server, rather than a Node-specific tool alongside systemd managing everything else. This reduces what you need to learn, monitor, and keep updated to a single system.

Tighter OS-level integration. Resource limits (memory, CPU), security sandboxing options (systemd supports meaningful process isolation directives), and dependency ordering (starting your app only after a database service is confirmed up, for example) are native systemd features that apply uniformly across any service, Node or otherwise, without needing an application-specific tool to replicate them.

No extra attack surface or update burden. PM2 is another piece of software with its own release cycle, its own potential vulnerabilities, and its own configuration to keep current; systemd's release cycle is tied to your OS's own update cadence, which most servers are already tracking regardless.

Where PM2 wins

Cluster mode is genuinely simpler. Node.js runs single-threaded by default, meaning a single Node process only utilizes one CPU core regardless of how many are available on your VPS. PM2's cluster mode spins up multiple instances of your app automatically, one per available CPU core by default, with built-in load balancing across them, achievable with a single flag (pm2 start app.js -i max). Replicating this under systemd requires either restructuring your app to use Node's own built-in cluster module directly in code, or running multiple systemd service instances with a separate reverse-proxy load-balancing configuration in front of them, both meaningfully more setup work for the same outcome.

Log management out of the box. PM2 automatically captures stdout/stderr per application, with built-in log rotation available through a companion module, and a simple command (pm2 logs) to tail them. systemd's journal (journalctl) does capture logs too, and can be configured well, but the defaults and the workflow for viewing application-specific logs feel noticeably less immediate for someone not already comfortable with journalctl's query syntax.

Zero-downtime reload with one command. pm2 reload app restarts your application's cluster instances one at a time, keeping at least some instances serving traffic throughout, achieving zero-downtime deploys without additional infrastructure. A comparable systemd-native setup requires either running multiple service instances behind a reverse proxy and orchestrating a rolling restart yourself, or accepting a brief interruption during restart, neither of which is as simple as PM2's single command.

A built-in monitoring view. pm2 monit and PM2's web-based dashboard (PM2 Plus, a separate paid product) give quick visibility into memory, CPU, and restart counts per application without configuring a separate monitoring stack, useful for a smaller team without dedicated infrastructure tooling already in place.

Bar chart comparing systemd and PM2 across five deployment factors: dependency footprint, cluster mode setup effort, zero-downtime reload effort, log management convenience, OS-level integration depth

Cluster mode: the biggest practical difference

This is worth its own emphasis because it is the single factor most likely to actually decide this choice for a real production app rather than a hobby project. If your VPS has multiple CPU cores (most do beyond the smallest tiers) and your Node app is CPU-bound in any meaningful way, request handling, JSON processing, any real computation, a single Node process leaves the additional cores entirely idle unless something distributes work across multiple instances.

PM2's cluster mode solves this with essentially no application code changes required, since it forks your app into multiple worker processes and load-balances incoming connections across them transparently. Achieving the same result under raw systemd requires either using Node's built-in cluster module directly in your application code (more control, more code to write and maintain) or running several separate systemd-managed instances on different ports with Nginx or another reverse proxy load-balancing across them (works well but is more moving parts to configure and keep synchronized).

For an app that genuinely benefits from multi-core utilization, this single factor often outweighs the "one less dependency" argument for systemd alone, since the operational simplicity PM2 provides here is substantial.

Zero-downtime reloads compared

For an app where any restart-induced downtime, even a few seconds, is unacceptable (a customer-facing API with real traffic, for example), PM2's built-in graceful reload is meaningfully easier to rely on correctly than assembling an equivalent systemd-based rolling deployment yourself. This is not to say systemd cannot achieve zero-downtime deploys, well-run systemd shops absolutely do, via socket activation and careful service unit design, but it is more advanced systemd knowledge than most teams deploying a single Node app have reason to invest in acquiring, compared to PM2's single documented command achieving the same practical outcome.

A comparison table

Factor systemd PM2
Already installed on the OS Yes No, separate install
Cluster mode (multi-core) Manual setup (code or multi-instance + proxy) Built in, one flag
Zero-downtime reload Advanced setup required Built in, one command
Log management journalctl, less Node-specific Built-in, Node-application-aware
Extra software to maintain None PM2 itself
Boot-time startup Native Via pm2 startup generating a systemd unit
Resource limits/sandboxing Native, granular Limited compared to systemd
Best fit Teams wanting minimal dependencies, comfortable with Linux tooling Teams wanting fast setup, multi-core utilization, and simpler day-to-day operations

Can you use both together?

Yes, and this is actually a common and sensible real-world configuration rather than an either-or choice: run PM2 to supervise your Node application (getting cluster mode, log management, and zero-downtime reloads), and use pm2 startup, PM2's own command for generating the appropriate configuration, to have systemd supervise PM2 itself, ensuring PM2 (and therefore your app) restarts automatically on server reboot. This gets you PM2's Node-specific conveniences while still relying on systemd as the ultimate root-level guarantee that things come back up after a server restart, combining the strengths of both rather than picking one exclusively.

FAQs

Does PM2 add noticeable overhead compared to running Node directly under systemd?

The overhead is small in most practical deployments, PM2's own process is lightweight, but it is a genuinely nonzero additional resource footprint compared to systemd supervising your app directly with nothing in between, worth considering specifically on a very resource-constrained small VPS where every bit of RAM matters.

Is PM2 cluster mode the same as running multiple separate app instances manually?

Conceptually similar, but PM2 handles the process forking, port sharing, and load balancing across instances automatically and transparently, whereas doing this manually under systemd requires you to configure separate service instances on different ports and set up your own reverse-proxy load-balancing rules to distribute traffic across them.

Do I need PM2 if my app is not CPU-bound?

Less critically, since the cluster mode benefit (multi-core utilization) matters most for CPU-bound workloads; for a mostly I/O-bound app (waiting on database or external API calls more than doing heavy computation), a single Node process under systemd can handle substantial concurrent load without needing multiple instances, making the case for PM2 rest more on its log management and reload convenience than on cluster mode specifically.

Is systemd harder to learn than PM2?

For someone already comfortable with general Linux server administration, systemd unit files are a small, well-documented additional skill; for someone newer to server management specifically, PM2's Node-focused documentation and simpler command set can feel more approachable initially, though both are genuinely learnable within a short period either way.

Does PM2 work well with Docker?

PM2 is less commonly used inside Docker containers, since container orchestration platforms (Docker Compose, Kubernetes) typically handle process restart and scaling at the container level themselves, making an in-container process manager somewhat redundant; for a Dockerized Node deployment, running Node directly as the container's main process, with restart policy handled by the orchestrator, is the more common and recommended pattern rather than layering PM2 inside the container as well.

Which is better for a hobby project or a single small app?

Either works fine; systemd avoids installing extra software for something simple, while PM2's simpler log-viewing command and one-line cluster mode can save time even for a small project, if you are not planning to become deeply familiar with journalctl. It is a reasonable personal preference decision at this scale rather than one with a clearly correct answer.

Should I use PM2's built-in monitoring dashboard or set up something separate?

PM2's own monit view and its cloud-based PM2 Plus dashboard are convenient for quick checks without extra setup, but for anything beyond a single small app, a dedicated monitoring solution (server-level monitoring, application performance monitoring) generally provides more depth and is worth setting up regardless of which process manager you use underneath it.

Conclusion

For a single Node.js app on a VPS with straightforward needs, systemd alone is a perfectly solid, dependency-free choice, particularly if you are already comfortable with Linux service management and do not need multi-core cluster mode. PM2 earns its place as an additional dependency specifically when cluster mode, simpler log handling, or truly zero-downtime reloads matter to your deployment, which is common enough for real production Node apps that PM2 remains the more widely recommended default for that use case.

Running PM2 under systemd's own supervision (via pm2 startup) combines both, giving you PM2's Node-specific conveniences with systemd's root-level restart guarantee, and is a reasonable default configuration rather than a compromise.

HostCloud's VPS plans give you full root access to configure either approach exactly as you need, with NVMe storage and multi-core options suited to running PM2's cluster mode effectively when your app benefits from it. See VPS plans at https://hostcloud.in.

Related posts