// hosting · Web Platform Advent #14
How to host a Node.js app: VPS, PaaS and serverless
The practical ways to deploy a Node.js application — VPS, managed PaaS, or serverless — plus PM2, a reverse proxy, environment variables and a sane deployment flow.
Hosting a Node.js app is different from hosting a static site or a PHP page. Node runs a long-lived process that owns its own HTTP server, so the host has to keep that process alive, restart it on crash, and route public traffic to it. This guide walks through the three realistic options and the pieces you need regardless of which you pick.
Three ways to host Node.js
Almost every deployment falls into one of these models. The right choice depends on how much of the server you want to manage and how your traffic behaves.
- VPS (self-managed) — you get a Linux machine and full root access. Maximum control and predictable cost, but you install and maintain Node, the process manager, the reverse proxy and TLS yourself.
- PaaS (platform-as-a-service) — you push code (often via Git) and the platform builds, runs and scales the process for you. Less control, faster to ship, usually metered.
- Serverless / functions — you deploy individual handlers instead of a running server. The platform starts them on demand. Great for spiky or low-traffic workloads, but stateless and subject to cold starts.
Keeping the process alive with PM2
On a VPS, running node server.js in your shell stops the moment you log out, and nothing restarts it after a crash. A process manager solves both. PM2 is the common choice:
npm install -g pm2
# start the app and name it
pm2 start server.js --name web
# restart automatically after a server reboot
pm2 startup
pm2 save
# useful day-to-day commands
pm2 list
pm2 logs web
pm2 restart web PM2 also runs your app in cluster mode to use every CPU core, which is the simplest way to scale a single box:
pm2 start server.js --name web -i max
A reverse proxy in front of Node
Don't expose Node directly on port 80/443. Put a reverse proxy such as Nginx in front: it terminates TLS, serves static files efficiently, and can route several apps on one machine. A minimal Nginx server block that forwards traffic to a Node app listening on port 3000:
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
} The Upgrade and Connection headers matter if your app uses WebSockets. For HTTPS, the usual route is a free certificate from Let's Encrypt via certbot, which edits this config for you.
Environment variables and configuration
Never hard-code secrets (database URLs, API keys) in your source. Read them from the environment with process.env, and let the platform inject them:
const port = process.env.PORT || 3000;
const dbUrl = process.env.DATABASE_URL;
app.listen(port, () => {
console.log(`listening on ${port}`);
}); On a VPS you can keep these in a .env file (loaded by a library, and excluded from Git) or pass them through PM2's ecosystem file. On a PaaS, you set them in the dashboard. Always read process.env.PORT — managed platforms assign the port for you.
A sane deployment flow
However you host, aim for a repeatable deploy rather than editing files on the server by hand:
- Pull the new code (
git pullor a CI artifact). - Install only production dependencies:
npm ci --omit=dev. - Run the build step if you have one (
npm run build). - Reload the process with zero downtime:
pm2 reload web.
On a PaaS this whole sequence is triggered by a git push; on a VPS you can script it or wire it to a CI runner.
Which option fits?
| Option | You manage | Best when |
|---|---|---|
| VPS | OS, Node, PM2, Nginx, TLS | You want control and predictable cost |
| PaaS | Just your code + env vars | You want to ship fast and scale easily |
| Serverless | Individual handlers | Spiky or low traffic, stateless work |
If you're starting out, a single well-configured VPS with PM2 and Nginx will comfortably run most Node apps and teaches you what the managed platforms automate. Move to a PaaS or serverless when scaling or operational overhead becomes the bottleneck — not before.