# How to keep a Node.js app running

A Node.js application is a long-lived process. If it crashes, or the server reboots, it must start
again on its own - otherwise Nginx has nothing to forward to and returns a 502 error. On TurboStack
you keep it running with the **pm2** process manager (a systemd service is the alternative).

pm2 keeps the app running with auto-restarts, manages several apps at once, and gives you monitoring
and log viewing in one place.

## Before you start

- **SSH access to the host** - see [SSH access](../../platform/hosts/ssh.md). Run these commands as
  your system user.
- **The Node.js runtime enabled** on the application, and your app listening on the local port set
  as `proxy_upstream_port` so Nginx can proxy to it - see [Configure Node.js](configure.md) and the
  [reverse proxy](../reverse-proxy/configure.md). When you enable the Node.js runtime, pm2 is
  installed for you by the node package manager, so there is nothing extra to install.

## Deploy and start your app under pm2

If you migrated from another environment, reinstall dependencies cleanly first so no incompatible or
corrupted modules are left behind:

```bash
cd ~/app
rm -rf node_modules      # only when migrating or dependencies changed
npm install              # rebuild node_modules
npm run build            # build the app (for example a Next.js build)
```

Then start it under pm2 and give it a name:

```bash
pm2 start npm --name app -- start     # runs "npm start"
# or run a file directly:
pm2 start server.js --name app
```

Check that it is running:

```bash
pm2 ls
```

## Make it survive reboots

TurboStack already provisions a platform-managed `pm2-<user>` system service that starts pm2 and
your saved processes at boot, so you do not run `pm2 startup` yourself (as a non-root user it only
prints a `sudo` line and cannot complete). What you must do is save the current process list so the
platform service brings the right apps back:

```bash
pm2 save       # save the current process list - run this again after every change
```

> [!IMPORTANT]
> Run `pm2 save` **every time** you add, rename or remove a process. Without it, pm2 restores an old
> list (or nothing) after a reboot, and your app stays down.

## Monitor and read logs

```bash
pm2 ls                 # list processes with status, CPU, memory and restart count
pm2 show app           # details for one process
pm2 logs app           # live logs (use --lines 200, --err or --out to narrow)
pm2 monit              # live dashboard: CPU/memory per app, status, restarts, real-time logs
```

## Restart after a change or deploy

```bash
pm2 restart app        # full restart
pm2 reload app         # zero-downtime reload (for cluster-mode apps)
```

When you change dependencies or move the app from another environment, reinstall cleanly first to
avoid incompatible modules:

```bash
rm -rf node_modules
npm install
pm2 restart app
```

## Check which process manager is configured

To see which manager each application user runs under, use the
[TurboStack CLI](../../api/cli.md):

```bash
tscli app backends
```

## Alternative: a systemd user service

Instead of pm2 you can run any long-lived app (Node.js, Python, a custom worker) as a **systemd user
service**. It needs no root, integrates with `journalctl` for logs, and restarts on crash and on
boot. Use pm2 when you want its process dashboard and zero-downtime reloads; use a systemd service
when you prefer one consistent way to run every background process on the host.

For the unit file and the `systemctl --user` commands, see
[How to manage user system services](../system-services/manage-user-services.md).

## Related

- [Configure Node.js](configure.md)
- [What is Node.js?](what-is.md)
- [Set the Node.js version](set-node-version.md)
- [Configure the reverse proxy](../reverse-proxy/configure.md)
- [How to manage user system services](../system-services/manage-user-services.md)
- [Deploy Medusa](../../applications/medusa/deploy.md)
