ADR-0044 — Vercel installs with its own Bun, from the frozen lockfile
The Vercel build installs with bun install --frozen-lockfile, using the Bun Vercel picks from bun.lock, instead of fetching Bun through bunx.
- Status: Approved
- Date: 2026-11-05
- Deciders: @puncoz
- Approved by: @puncoz
- Approved on: 2026-11-05
- Supersedes: ADR-0042 in part: decision 5's
installCommand - Superseded by: —
- Design documents:
../architecture/system.mdx. Nothing a reader sees changes, so there is no app flow (ADR-0008).
Context
- ADR-0042 decision 5 pinned Bun by installing as
bunx bun@1.4.4 install --frozen-lockfile. - The first build of
mainto start after ADR-0043 (commitf94821b) failed in the install, which printed "Resolving dependencies", "Resolved, downloaded and extracted [29]" and "Saved lockfile", thenCommand "bunx bun@1.4.4 install --frozen-lockfile" exited with 1. Bun 1.4.4 never reported on the lockfile. When it refuses a lockfile, it prints that the lockfile is frozen. main'spackage.jsonandbun.locklist the same ranges, every dependency in the lockfile has an entry, and the owner'sbun.lockis the one onmain.- The npm package
bun@1.4.4sets up its binary in apostinstallscript (node install.js). The likely cause is that this did not happen whenbunxinstalled it on Vercel. This was not reproduced, because that means running an install. - The owner's last successful build (
e2f4ca7, beforevercel.jsonexisted) used Vercel's own install. Its log reads "Detectedbun.lockgenerated by bun@1.4.x", thenbun install v1.4.4 (38afee6c8). That is the same Bun build as the owner's machine. Vercel documents only "Bun 1" and picks the version from the lockfile.
Decision
"installCommand": "bun install --frozen-lockfile". The install uses the Bun Vercel picks frombun.lock, which is 1.4.4 today, and fails when the lockfile does not matchpackage.json. Bun is not fetched throughbunxornpx.
The rest of ADR-0042 decision 5 (Bun 1.4.4 as the owner's version, the lockfile binding), as amended by ADR-0043 (Node 26), stands.
Options considered
| Option | Pros | Cons | Verdict |
|---|---|---|---|
bun install --frozen-lockfile, Vercel's Bun | Ran on Vercel as Bun 1.4.4 (38afee6c8); nothing downloaded; the lockfile is binding | The exact patch version is Vercel's pick; a new Bun is seen only in the build log | Chosen |
npx --yes bun@1.4.4 install --frozen-lockfile | An exact pin; npm runs Bun's setup script | Never run on Vercel here; downloads Bun every build | Rejected |
No installCommand (Vercel's default) | Exactly the last successful build | The lockfile is not enforced: a mismatch is re-resolved silently | Rejected |
Keep bunx bun@1.4.4 | The ADR-0042 pin | Fails on Vercel | Rejected |
Consequences
Positive
- The install that has worked on Vercel is used again, and the lockfile stays binding.
- No Bun download per build.
Negative / accepted trade-offs
- If Vercel ever picks a different Bun for this lockfile, the build log shows it first. The owner compares it with their own
(
bun --version).
Content invariants
None touched: the same pages are built from the same lockfile.
Security considerations
- Supply chain.
--frozen-lockfilestill installs exactlybun.lock. Bun itself now comes from Vercel's build image rather than from npm, so the npmbunpackage is no longer downloaded or run in the build. - Residual risk: the Bun version is Vercel's choice, read from the lockfile, and visible in each build log.
Implementation notes
-
vercel.json:"installCommand": "bun install --frozen-lockfile". -
src/lib/vercel-config.test.ts: the install command is exactly that, and neither the install nor the build command usesbunx. - Not testable here: the next build of
maininstalls withbun install v1.4.4and passes the frozen check. -
bun run test,bun run types:checkandbunx next buildpass.bun run lintstill fails with "typescript-eslint does not support TS 7.0".
Docs to update on implementation
-
content/docs/maintain/architecture/system.mdx: theinstallCommandrow. -
AGENTS.md§5: the Hosting row. -
content/docs/maintain/adr/index.mdx: the row and the next free number. ADR-0042's Superseded by.