Node.js Fundamentals Best Practices
A checklist for running Node.js services safely in production - version discipline, environment hygiene, and respect for the single-threaded model.
Search across all documentation pages
A checklist for running Node.js services safely in production - version discipline, environment hygiene, and respect for the single-threaded model.
engines in package.json and enforce in CI. Use engine-strict=true or a preinstall gate script..nvmrc or .node-version and match Docker base images. node:24.18.0-bookworm-slim, not node:latest.process.version at startup and expose it in /health. Speeds incident triage when fleets drift."type": "module"). Document any CJS exception with an ADR.node: prefix for built-in imports. import fs from 'node:fs/promises' clarifies intent.fetch, node:test, and node:assert before npm equivalents. Fewer supply-chain surfaces.package-lock.json committed and use npm ci in CI. Reproducible installs across machines.process.env after boot except in tests. Treat env as immutable configuration.AsyncLocalStorage for request context.NODE_ENV=production in deployed environments. Some libraries change behavior based on it.process.env dumps. Redact in structured logs.SIGTERM and SIGINT for graceful shutdown. Close servers and DB pools before exit.process.on('unhandledRejection') to log and exit.JSON.parse.node user.--trace-warnings and --trace-deprecation in CI. Catch upgrade debt before production.process.report). Practice before the first 3 a.m. page.Version drift is the root cause of most "works locally" incidents - wrong APIs, failed native builds, and unmatched security patches.
New services should use ESM on Node 24. CJS is legacy maintenance - exceptions need an ADR and sunset date.
Many libraries (Express in production mode, some log formatters) still branch on it. Set explicitly - do not rely on absence.
>=24.18.0 <25 for Node 24 Active LTS. During migration, document a temporary dual-range with an expiry date.
Treat critical/high severities as blockers. Fundamentals list focuses on runtime; see Security section for full policy.
Orchestrators may restart pods with stale images. Health output proves the running binary matches the intended patch.
Module-level singletons (DB pool, config) are fine. Per-request data on globals is not - use AsyncLocalStorage.
Add to .npmrc:
engine-strict=true
Allowed if production stays pinned Node 24 and CI tests against the production runtime - not dev-only shortcuts.
Every release candidate and within one week of any Node security advisory affecting your major line.
No. This list covers fundamentals; pair with Event Loop Best Practices for async performance.
status, node version, and build/git SHA. Optional: ltsPolicy field from your version gate script.
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.
Reviewed by Chris St. John·Last updated Jul 16, 2026