Bun 04 ⚡ Installing Dependencies with Bun’s Ultra-Fast Lockfile (bun.lockb)
Bun’s package manager is defined by its lockfile strategy. For its first two years, Bun used a binary lockfile named bun.lockb, which was faster to parse but opaque to review, Git diffs, and merge tools. In December 2024, Bun introduced a text-based alternative (bun.lock), and since Bun v1.2, it has become the default. This chapter covers both formats, the migration path, and the --frozen-lockfile mechanism that makes CI installs deterministic.
Key point: Bun v1.2 changed the default lockfile from binary bun.lockb to text-based bun.lock. The text format is diffable, mergeable, and 30% faster for cached installs. Existing projects must migrate explicitly; bun install alone does not rewrite the lockfile format.
Why Bun’s lockfile evolved
The binary review problem. Binary files cannot be reviewed in pull requests, merged with standard Git tooling, or inspected without running Bun. The bun.lockb format prioritized parsing speed at the cost of every downstream workflow: code review, merge conflict resolution, and CI diffing . The Bun team acknowledged that the most common feedback from teams migrating from npm, pnpm, or Yarn was about this binary format .
The text format advantage. bun.lock is JSONC (JSON with comments), similar to tsconfig.json. GitHub renders it in diffs, VS Code syntax-highlights it, and merge conflicts can be resolved by hand . The performance cost is negative: cached installs using the text lockfile are 30% faster than cached installs with the binary lockfile. A benchmark from Bun v1.1.39 showed 45.8ms for text versus 60.4ms for binary on a warm cache .
The migration problem. Bun does not automatically rewrite bun.lockb to bun.lock. The migration requires an explicit command: bun install --save-text-lockfile --frozen-lockfile --lockfile-only, followed by deleting the old binary file . Running bun install on a project with an existing bun.lockb continues to use the binary format unless this migration is performed.
The CI determinism problem. --frozen-lockfile is the flag that makes lockfile verification mandatory. It installs the exact versions recorded in the lockfile and fails if package.json and the lockfile disagree. The bun ci command is a convenience alias for bun install --frozen-lockfile .
The trade-off. The text format is slower to parse on a cold install, but faster on warm installs due to better caching. The binary format is smaller and faster to parse but incompatible with standard review workflows. The text format is the future; the binary format remains supported for backward compatibility .
a. Installing dependencies and generating the lockfile
The bun install command reads package.json, resolves the dependency graph, downloads packages, and writes the lockfile. In Bun v1.2+, the default lockfile is bun.lock. In earlier versions or projects with an existing bun.lockb, the binary format is used unless migration is performed.
# Standard install (writes bun.lock in v1.2+)
bun install
# Generate the lockfile without installing to node_modules
bun install --lockfile-only
# Install without modifying the lockfile
bun install --no-save
The --lockfile-only flag resolves dependencies and writes bun.lock without creating node_modules or populating the global cache with packages. It is useful for generating a lockfile in CI or for reviewing dependency changes before installation .
Bun automatically migrates existing lockfiles from other package managers when no bun.lock exists. The supported formats are package-lock.json (npm, lockfileVersion 2, 3, or 4), yarn.lock (Yarn v1), and pnpm-lock.yaml (pnpm v7+) . The migration happens during bun install; the original lockfile is not deleted.
b. Migrating from bun.lockb to bun.lock
The migration command generates the text lockfile using the existing binary lockfile as the source of truth, preserving all resolved versions and metadata.
# Generate bun.lock from bun.lockb
bun install --save-text-lockfile --frozen-lockfile --lockfile-only
# Remove the old binary lockfile
rm bun.lockb
The --save-text-lockfile flag tells Bun to write bun.lock instead of bun.lockb. The --frozen-lockfile flag prevents any resolution changes during the migration. The --lockfile-only flag avoids installing packages, making the migration fast and safe .
Once bun.lock exists, bun install uses it and ignores bun.lockb. The binary file can be deleted after the migration. Bun will continue to support the binary format for some time, but the text format is the default for all new projects .
c. CI installs with frozen lockfiles
The --frozen-lockfile flag is the CI safeguard. It ensures that the install uses exactly the versions recorded in the lockfile and fails if package.json has changed in a way that would require a lockfile update.
# CI install
bun install --frozen-lockfile
# Convenience alias
bun ci
The flag fails with an error if package.json and bun.lock are out of sync. This prevents a CI build from silently resolving new versions or modifying the lockfile . The bun ci command is functionally identical and is the recommended form for CI pipelines .
The lockfile hash can be inspected for caching purposes. bun pm hash generates a hash from the lockfile, and bun pm hash-print prints the stored hash. This is useful for constructing CI cache keys that invalidate when dependencies change .
Complete Example Session
# ============================================
# PART 1: STANDARD INSTALL
# ============================================
bun install
# Writes bun.lock (v1.2+)
# Populates node_modules
# ============================================
# PART 2: INSPECT THE LOCKFILE
# ============================================
head -n 20 bun.lock
# JSONC format with dependency entries
# ============================================
# PART 3: LOCKFILE-ONLY
# ============================================
bun install --lockfile-only
# Writes bun.lock without installing packages
# ============================================
# PART 4: MIGRATE FROM BINARY
# ============================================
# If bun.lockb exists:
bun install --save-text-lockfile --frozen-lockfile --lockfile-only
rm bun.lockb
# bun.lock now exists and is used by future installs
# ============================================
# PART 5: CI INSTALL
# ============================================
bun install --frozen-lockfile
# Fails if package.json and lockfile disagree
# ============================================
# PART 6: CI ALIAS
# ============================================
bun ci
# Equivalent to bun install --frozen-lockfile
# ============================================
# PART 7: AUTOMATIC MIGRATION FROM NPM
# ============================================
# With package-lock.json present and no bun.lock:
bun install
# Migrates package-lock.json to bun.lock
# ============================================
# PART 8: LOCKFILE HASH
# ============================================
bun pm hash
# Prints the lockfile hash for CI caching
The eight parts trace the lockfile lifecycle: standard install, inspection, lockfile-only generation, binary migration, frozen install, CI alias, npm migration, and hash generation.
Quick Reference
Lockfile Formats
| Format | File | Default Since | Reviewable |
|---|---|---|---|
| Text | bun.lock | v1.2 | Yes (JSONC) |
| Binary | bun.lockb | Pre-v1.2 | No |
Install Commands
| Command | Effect |
|---|---|
bun install | Install and write lockfile |
bun install --lockfile-only | Write lockfile without installing |
bun install --no-save | Install without writing lockfile |
bun install --frozen-lockfile | Fail if lockfile would change |
bun ci | Alias for --frozen-lockfile |
Migration
| Task | Command |
|---|---|
| Binary to text | bun install --save-text-lockfile --frozen-lockfile --lockfile-only |
| npm to Bun | bun install (auto-migrates package-lock.json) |
| Yarn to Bun | bun install (auto-migrates yarn.lock) |
Best Practices
✅ Do This:
bun ci
<!-- Use the CI alias for frozen installs --> # ✅
bun install --save-text-lockfile --frozen-lockfile --lockfile-only
<!-- Migrate from binary explicitly --> # ✅
bun pm hash
<!-- Generate hash for CI cache keys --> # ✅
❌ Don’t Do This:
# Assume bun install migrates bun.lockb automatically
<!-- Migration requires --save-text-lockfile --> # ❌
# Commit both bun.lock and bun.lockb
<!-- Only one lockfile should be authoritative --> # ❌
# Use --no-save in CI
<!-- Lockfile must be respected, not ignored --> # ❌
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
| Lockfile not migrating | No --save-text-lockfile flag | Use the migration command |
| CI fails with frozen lockfile | package.json changed without lockfile update | Run bun install locally and commit lockfile |
| Both lockfiles present | Migration incomplete | Delete bun.lockb after migration |
| Git cannot diff lockfile | Still using bun.lockb | Migrate to bun.lock |
| npm lockfile not migrating | bun.lock already exists | Delete bun.lock and re-run bun install |
Real-World Examples
1. Standard Install
bun install
2. Lockfile-Only
bun install --lockfile-only
3. Migrate from Binary
bun install --save-text-lockfile --frozen-lockfile --lockfile-only
rm bun.lockb
4. CI Install
bun ci
5. Frozen Install
bun install --frozen-lockfile
6. Lockfile Hash
bun pm hash
7. Auto-Migrate npm
bun install
# package-lock.json → bun.lock
8. Auto-Migrate Yarn
bun install
# yarn.lock → bun.lock
9. Skip Lockfile
bun install --no-save
10. Inspect Lockfile
head -n 20 bun.lock
Visual
Lockfile Evolution
┌──────────────────────────────────────────────┐
│ Pre-v1.2 │
│ │
│ bun.lockb (binary) │
│ - Fast parse │
│ - Not diffable │
│ - Not mergeable │
└──────────────────┬───────────────────────────┘
│
│ Migration
▼
┌──────────────────────────────────────────────┐
│ v1.2+ │
│ │
│ bun.lock (text, JSONC) │
│ - Diffable │
│ - Mergeable │
│ - 30% faster on warm cache │
└──────────────────────────────────────────────┘
CI Install Flow
┌──────────────────────────────────────────────┐
│ bun ci / bun install --frozen-lockfile │
└──────────────────┬───────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ Lockfile matches package.json? │
│ ├─ YES → Install exact versions │
│ └─ NO → FAIL │
└──────────────────┬───────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ node_modules populated from lockfile │
└──────────────────────────────────────────────┘
Summary
| Item | Value |
|---|---|
| Default lockfile (v1.2+) | bun.lock (text) |
| Legacy lockfile | bun.lockb (binary) |
| Text format | JSONC |
| Cached install speed | 30% faster with text |
| CI flag | --frozen-lockfile |
| CI alias | bun ci |
| Migration command | --save-text-lockfile --frozen-lockfile --lockfile-only |
| Auto-migration sources | package-lock.json, yarn.lock, pnpm-lock.yaml |
Key takeaways:
- Bun v1.2 changed the default lockfile to text.
bun.lockis reviewable, mergeable, and faster on warm caches than the old binary format . - The binary format is legacy, not removed. Existing
bun.lockbfiles continue to work, but new projects and migrated projects usebun.lock. - Migration requires an explicit command.
bun installdoes not automatically rewrite the lockfile format. The migration command uses the existing lockfile as the source of truth . --frozen-lockfileis the CI safeguard. It prevents silent resolution changes and fails ifpackage.jsonand the lockfile disagree.bun ciis the shorthand .- Bun auto-migrates from npm, Yarn, and pnpm. When no
bun.lockexists,bun installreads the existing lockfile and produces a Bun lockfile .
Remember: The lockfile is the reproducibility contract. Bun’s move from binary to text was a recognition that reviewability matters as much as raw speed. Use bun.lock, commit it, and enforce it with bun ci. The binary format remains for legacy projects, but the text format is the standard.
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!