The package manager war, settled by your lockfile
In 2026 the four contenders — npm, yarn, pnpm, bun — are all viable. The differences that matter for *deploys* are: which lockfile is committed, how you run a clean install, and how the platform detects which one to use. Get those three right and switching is painless.
The golden rule: commit exactly one lockfile, and make your install command match it. Mixed lockfiles are the number-one cause of "works locally, breaks in CI."
How platforms auto-detect
Most platforms (PandaStack included) detect the package manager from the lockfile present in the repo:
| Lockfile | Package manager | Clean-install command |
|---|---|---|
package-lock.json | npm | npm ci |
yarn.lock | yarn | yarn install --frozen-lockfile |
pnpm-lock.yaml | pnpm | pnpm install --frozen-lockfile |
bun.lockb / bun.lock | bun | bun install --frozen-lockfile |
Note the frozen/CI flavor of each command. In a deploy you want a reproducible install that fails if the lockfile is out of date — never a command that silently updates dependencies.
Switching to pnpm
pnpm is popular for monorepos and disk efficiency. To switch:
# locally
npm uninstall -g # optional cleanup
corepack enable
pnpm import # converts package-lock.json -> pnpm-lock.yaml
rm package-lock.json # remove the old lockfile!
pnpm install
git add pnpm-lock.yaml && git rm package-lock.jsonThen set the install command in your platform to pnpm install --frozen-lockfile. The critical step people forget is deleting the old package-lock.json — leaving it confuses auto-detection.
Switching to bun
bun is the fastest installer and runtime. To switch:
bun install # generates bun.lock (text) / bun.lockb (binary)
rm package-lock.json
git add bun.lock && git rm package-lock.jsonInstall command: bun install --frozen-lockfile. If you also want bun as the *runtime*, your start command becomes bun run start or bun server.ts. You can use bun just for installs and still run Node — they're independent choices.
Switching to yarn (modern)
Yarn Berry (v3/v4) uses Plug'n'Play by default, which some tools don't like. For deploy simplicity, many teams use the node-modules linker:
# .yarnrc.yml
nodeLinker: node-modulescorepack enable
yarn install
git add yarn.lock .yarnrc.ymlInstall command: yarn install --immutable (Berry) or yarn install --frozen-lockfile (classic).
Pinning the version with Corepack
The cleanest way to guarantee the *same* package manager version locally and in CI is Corepack (bundled with Node). Add a packageManager field:
{
"packageManager": "pnpm@9.12.0"
}Many build environments honor this field automatically via Corepack, eliminating "works on my machine" version drift. It's the single best habit when switching managers.
Setting the install command on PandaStack
PandaStack auto-detects the manager from your lockfile, but you can override the install command explicitly:
- 1Open the service → Build & Deploy settings.
- 2Set Install command to the frozen-install for your manager (table above).
- 3Adjust Build and Start if you switched the runtime (e.g.,
bun run build). - 4Redeploy and watch the live build logs — the first lines show which manager ran.
Common breakage and fixes
- Two lockfiles committed. Delete all but the one you want. This is the top cause of nondeterministic installs.
--frozen/--immutablefails. Your lockfile is out of date. Run a normal install locally, commit the updated lockfile, redeploy.- Build can't find pnpm/bun. Enable Corepack in the install step (
corepack enable && pnpm install --frozen-lockfile) or use an image that ships it. - Monorepo installs the wrong workspace. Use the manager's filter (
pnpm --filter,yarn workspace,bun --filter) and/or set a root directory. - Native modules differ. bun and pnpm can hoist differently than npm; if a native dep misbehaves, check the hoisting/linker settings.
Which should you pick?
- npm: zero-config, ships with Node, fine for most apps.
- pnpm: best for monorepos and strict dependency isolation; great disk usage.
- yarn: mature, good monorepo support; PnP is powerful but occasionally fiddly.
- bun: fastest installs and an all-in-one runtime/test/bundler; ecosystem maturing fast.
For deploys, any of them works as long as you commit one lockfile, use the frozen install, and pin the version with Corepack.
References
- npm ci: https://docs.npmjs.com/cli/v10/commands/npm-ci
- pnpm CLI: https://pnpm.io/cli/install
- bun install: https://bun.sh/docs/cli/install
- Yarn immutable installs: https://yarnpkg.com/cli/install
- Corepack: https://nodejs.org/api/corepack.html
---
Want the platform to detect npm, yarn, pnpm, or bun automatically — and let you override when needed? PandaStack does both. Deploy free at https://dashboard.pandastack.io