Runtime Ops Basics
10 examples for operating long-lived Node.js 24 processes in production - 7 basic and 3 intermediate.
Prerequisites
mkdir prod-api && cd prod-api
npm init -y
npm pkg set type=module
npm install express@5 pg
npm install -D typescript@5.6 @types/nodeFor shutdown and deploy patterns, see Graceful Shutdown and Zero-Downtime Deploys.
Basic Examples
1. Process Supervision Model
Kubernetes / ECS / systemd / PM2
-> starts `node dist/main.js`
-> restarts on crash exit code != 0
-> sends SIGTERM on deploy or scale-in
-> reads stdout logs
- Your app cooperates with SIGTERM; the platform handles restarts
- Do not double-supervise (PM2 inside K8s pod)
2. Structured Boot Log
console.log(JSON.stringify({
event: "boot",
node: process.version,
env: process.env.NODE_ENV,
pid: process.pid,
}));- Confirms version and config in CloudWatch/Loki on every pod start
- Never log secret env values
3. Health and Readiness
app.get("/health", (_req, res) => res.json({ status: "ok" }));
app.get("/ready", async (_req, res) => {
const ok = await pool.query("SELECT 1");
res.status(ok ? 200 : 503).json({ status: ok ? "ready" : "not_ready" });
});- Orchestrator uses these for routing and restarts
- See Health & Readiness Probes
4. uncaughtException Policy
process.on("uncaughtException", (err) => {
console.error(JSON.stringify({ event: "uncaughtException", message: err.message, stack: err.stack }));
// Policy A: exit and let supervisor restart (recommended for APIs)
process.exit(1);
});- Document Policy A (exit) vs Policy B (log and continue) per service in runbook
- Unknown process state after uncaughtException; exit is safer for HTTP APIs
5. unhandledRejection Policy
process.on("unhandledRejection", (reason) => {
console.error(JSON.stringify({ event: "unhandledRejection", reason: String(reason) }));
process.exit(1);
});- Express 5 forwards async errors; still guard top-level workers
- Fail fast so alerts fire
6. Memory Visibility
app.get("/metrics/memory", (_req, res) => {
const m = process.memoryUsage();
res.json({
rss: m.rss,
heapUsed: m.heapUsed,
heapTotal: m.heapTotal,
external: m.external,
});
});- Protect admin routes with auth or disable in production
- Prefer Prometheus
nodejs_heap_size_bytesexporter for real monitoring
7. NODE_OPTIONS Heap Cap
NODE_OPTIONS="--max-old-space-size=384"- Set below container memory limit to leave room for native buffers and libuv
- Derive from load test RSS, not default 512 MB guess
Intermediate Examples
8. Graceful Shutdown Skeleton
const server = app.listen(port, "0.0.0.0");
function shutdown(signal: string) {
console.log(JSON.stringify({ event: "shutdown", signal }));
server.close(async () => {
await pool.end();
process.exit(0);
});
setTimeout(() => process.exit(1), 30_000).unref();
}
process.on("SIGTERM", () => shutdown("SIGTERM"));
process.on("SIGINT", () => shutdown("SIGINT"));- See Graceful Shutdown for full pattern
9. PM2 on a VM (When Not on K8s)
// ecosystem.config.cjs
module.exports = {
apps: [{
name: "api",
script: "dist/main.js",
instances: 2,
exec_mode: "cluster",
max_memory_restart: "512M",
kill_timeout: 30_000,
listen_timeout: 10_000,
}],
};pm2 start ecosystem.config.cjs
pm2 save- PM2 for VMs only - PM2 & systemd
10. On-Call First Questions
| Symptom | Check |
|---|---|
| High CPU | Recent deploy? Traffic spike? Infinite loop in logs? |
| High memory | Heap leak? max-old-space-size vs limit? |
| 502 from LB | Pods ready? SIGTERM drain? Upstream timeout? |
FAQs
Who supervises Node in Kubernetes?
kubelet + Deployment controller. Your app handles SIGTERM; K8s restarts failed containers.
Should we use cluster mode in containers?
No. Scale pod replicas instead of Node cluster module inside one container.
How long should shutdown take?
Under terminationGracePeriodSeconds (often 30-45s). Match LB deregistration delay + DB pool close.
File logging in prod?
Stdout only. Agents ship logs off-node.
What Node version in prod?
Node 24 LTS, matching CI and Docker base image.
Runtime ops vs platform deploy?
Platform deploy is where/how you run containers. Runtime ops is how the Node process behaves once running.
Related
- Graceful Shutdown - SIGTERM drain
- Zero-Downtime Deploys - rolling updates
- PM2 & systemd - VM supervision
- On-Call Runbook Starters - incident triage
- Runtime Ops Best Practices - section checklist
Stack versions: This page was written for Node.js 24.18.0 (Active LTS), npm 10+, TypeScript 5.6+, Express 5, Fastify 5, and NestJS 11.