Declare a Node.js version requirement in package.json
Use engines to describe tested Node versions, add install-time checks, and align local tooling, CI, and deployment runtimes.
Declare the Node.js versions your project supports in package.json under engines.node. This is a compatibility declaration, not an instruction that automatically installs or switches Node.
Declare a tested range
{
"engines": {
"node": "22.x || 24.x"
}
}
This example allows the two listed major versions. Choose the range from your actual test matrix. >=22 <25 also permits major version 23, while ^22.0.0 stays below 23. Do not declare versions you have not checked simply to avoid a warning.
An engines.npm entry can describe a compatible npm range. Treat it separately from the Node range because the two version numbers do not advance together.
Add install-time checks
With npm, engines is normally advisory. A project .npmrc can request stricter enforcement:
engine-strict=true
This makes incompatible engine requirements an installation error under normal npm operation. It is not a security boundary: options such as --force can override checks, and running the program directly is outside the install check. Have CI verify the actual runtime too.
Package managers differ. pnpm distinguishes the current project's requirements from dependency engine checks, and the configuration location depends on its version. Yarn Classic and newer Yarn releases should not be assumed to share npm's behavior.
Select a local runtime
For nvm or fnm users, a .nvmrc might contain:
24
Run nvm use or configure the tool's shell integration. Merely creating the file does not make every shell switch versions automatically. fnm's directory-change integration also needs to be enabled. Volta uses its own volta field in package.json.
Align CI and deployment configuration with the declared range. A Docker base image such as node:24 selects the container runtime independently of engines. Hosted platforms, including Heroku, apply their own supported versions and configuration precedence; verify those platform rules.
Pin the package manager separately
A packageManager field can identify an exact pnpm or Yarn release for Corepack to use. Corepack must be installed and enabled where required; Node.js 25 and later no longer bundle it. The field alone does not block every directly invoked package manager. Record the version in CI and use the project's intended lock file.
Libraries should declare all versions they actually test and maintain. Applications can choose a narrower operational standard. In both cases, repeatable checks are stronger evidence than a permissive range.
References: npm package.json fields, pnpm settings, and Corepack.
Related reading
Contact us
Join the community
to join the community
Try Guance
Start online and pay only for what you use.
Get startedChoose a Guance plan