pnpm install --prod (-P): install only production dependencies
- tool
- pnpm
- command
- pnpm install
- flag
- -P, --prod
- default
- false (true when NODE_ENV=production)
pnpm install --prod (short -P) installs dependencies and optionalDependencies but not devDependencies. Use it for production servers and the final stage of Docker images, where test frameworks, bundlers and type checkers are dead weight. pnpm also switches to this mode by itself when NODE_ENV=production. The lockfile is not changed by the flag.
Full install and --prod
cat > package.json <<'EOF'
{
"name": "demo",
"version": "1.0.0",
"dependencies": { "is-number": "7.0.0" },
"devDependencies": { "is-odd": "3.0.1" }
}
EOF
npx --yes pnpm@9 install >/dev/null 2>&1
echo "--- pnpm install"
ls node_modules
rm -rf node_modules
npx --yes pnpm@9 install --prod --frozen-lockfile >/dev/null 2>&1
echo "--- pnpm install --prod --frozen-lockfile"
ls node_modules
rm -rf node_modules
NODE_ENV=production npx --yes pnpm@9 install --frozen-lockfile >/dev/null 2>&1
echo "--- NODE_ENV=production"
ls node_modulesOutput
--- pnpm install is-number is-odd --- pnpm install --prod --frozen-lockfile is-number --- NODE_ENV=production is-number
Only is-number is linked with --prod and under NODE_ENV=production. Combining it with --frozen-lockfile (the CI default) guarantees the versions are the committed ones.
Related options
| Option | Installs |
|---|---|
| (none) | dependencies, devDependencies, optionalDependencies |
| -P, --prod | dependencies and optionalDependencies |
| -D, --dev | Only devDependencies |
| --no-optional | Skip optionalDependencies |
| --prod=false | Force the full install even when NODE_ENV=production |
| pnpm prune --prod | Remove devDependencies from an existing node_modules |
| pnpm deploy --prod DIR | Copy one workspace package with its production dependencies into DIR |
In a Dockerfile
FROM node:24-slim AS build
RUN corepack enable
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
COPY . .
RUN pnpm run build && pnpm prune --prod
FROM node:24-slim
WORKDIR /app
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist
CMD ["node", "dist/server.js"]The build stage needs dev tools, so it installs everything and prunes afterwards. In a workspace, pnpm deploy is the better tool because it also resolves workspace: dependencies into real copies.
Pitfalls
- A runtime import listed under
devDependenciesfails only in production, with Cannot find module. Move it withpnpm add pkg. NODE_ENV=productionset in a base image silently removes dev tools from build steps; pass--prod=falsethere.pnpm install --prodin a workspace applies to every package; limit it with--filter, see pnpm --filter.- npm calls the same option
--omit=dev: see npm install --omit=dev.
FAQ
Does NODE_ENV=production make pnpm skip devDependencies?
Yes. When NODE_ENV is production, pnpm install behaves as if --prod were passed. Use --prod=false or --dev in a build step that needs dev tools under that environment.
How do I create a production node_modules for one package of a monorepo?
Use pnpm deploy: pnpm --filter api deploy --prod out/ copies the package and its production dependencies, with workspace dependencies resolved, into a self-contained folder for a Docker image.
Does --prod change pnpm-lock.yaml?
No. The lockfile always describes all dependencies; --prod only decides what is linked into node_modules.