Deploying Node Applications in JavaScript

Introduction

Local node server.mjs is only the first step. Deployment means running your app reliably on a server or platform with the right Node version, environment variables, process manager, and health checks. This chapter outlines a practical path from dev laptop to production—aligned with how many teams ship Node APIs and Next.js apps.

Prerequisites

Production Checklist

  • Pin Node LTS version (.nvmrc or host image)
  • Set NODE_ENV=production
  • Provide secrets via host env, not git
  • Run npm ci from lockfile (not npm install on server)
  • Expose one HTTP port; put TLS on reverse proxy
  • Log to stdout; aggregate with host tooling

Build vs Run

Pure Node scripts may have no build step. Bundled apps compile first:

bash
npm ci
npm run build
npm start

Read each project’s README—Next.js and Vite differ from a single server.mjs.

Process Manager — PM2 Example

bash
npm install -g pm2
pm2 start index.mjs --name my-api
pm2 save
pm2 startup

Useful commands:

bash
pm2 list
pm2 logs my-api
pm2 restart my-api

PM2 restarts crashed processes and supports cluster mode for multi-core.

Reverse Proxy

Run Node on 127.0.0.1:3000; nginx or Caddy forwards public HTTPS:

plaintext
client → HTTPS → nginx → http://127.0.0.1:3000 → Node app

Node app does not need root privileges on port 443.

Health Endpoint

javascript
// health route for load balancers
if (url.pathname === "/health") {
  res.writeHead(200, { "Content-Type": "application/json" });
  res.end(JSON.stringify({ status: "ok", uptime: process.uptime() }));
  return;
}

Orchestrators ping /health before sending traffic.

Platform Deploy (PaaS)

Services like Railway, Render, Fly.io, or Vercel (for Next.js):

  1. Connect git repository
  2. Set build/start commands
  3. Configure env vars in dashboard
  4. Deploy on push

Same code—less server admin than raw VPS.

Zero-Downtime Restarts

Rolling deploys start new instances before stopping old ones. With PM2:

bash
pm2 reload my-api

Drain connections using graceful shutdown.

Mini Example: Start Script in package.json

json
{
  "name": "my-api",
  "type": "module",
  "engines": {
    "node": ">=22"
  },
  "scripts": {
    "start": "node server.mjs"
  }
}

Host reads engines to warn on version mismatch.

FAQ

Docker?

Package app + Node image; pass env at docker run—common in teams but optional for first deploy.

How many instances?

Scale horizontally behind a load balancer when CPU or traffic grows—one process per core is a starting heuristic.

Logs and monitoring?

Ship stdout to your host’s log stack; add APM (Datadog, Sentry) for errors and latency.

What comes next?

Internationalization API and other extension chapters 86–95.