Bun provides an alternative package installation strategy called isolated installs that creates strict dependency isolation similar to pnpm's approach. This mode prevents phantom dependencies and ensures reproducible, deterministic builds.
What are isolated installs?
Isolated installs create a non-hoisted dependency structure where packages can only access their explicitly declared dependencies. This differs from the traditional "hoisted" installation strategy used by npm and Yarn, where dependencies are flattened into a shared node_modules
directory.
Key benefits
- Prevents phantom dependencies — Packages cannot accidentally import dependencies they haven't declared
- Deterministic resolution — Same dependency tree regardless of what else is installed
- Better for monorepos — Workspace isolation prevents cross-contamination between packages
- Reproducible builds — More predictable resolution behavior across environments
Using isolated installs
Command line
Use the --linker
flag to specify the installation strategy:
# Use isolated installs
bun install --linker isolated
# Use traditional hoisted installs
bun install --linker hoisted
Configuration file
Set the default linker strategy in your bunfig.toml
:
[install]
linker = "isolated"
Default behavior
By default, Bun uses the hoisted installation strategy for all projects. To use isolated installs, you must explicitly specify the --linker isolated
flag or set it in your configuration file.
How isolated installs work
Directory structure
Instead of hoisting dependencies, isolated installs create a two-tier structure:
node_modules/
├── .bun/ # Central package store
│ ├── package@1.0.0/ # Versioned package installations
│ │ └── node_modules/
│ │ └── package/ # Actual package files
│ ├── @scope+package@2.1.0/ # Scoped packages (+ replaces /)
│ │ └── node_modules/
│ │ └── @scope/
│ │ └── package/
│ └── ...
└── package-name -> .bun/package@1.0.0/node_modules/package # Symlinks
Resolution algorithm
- Central store — All packages are installed in
node_modules/.bun/package@version/
directories - Symlinks — Top-level
node_modules
contains symlinks pointing to the central store - Peer resolution — Complex peer dependencies create specialized directory names
- Deduplication — Packages with identical package IDs and peer dependency sets are shared
Workspace handling
In monorepos, workspace dependencies are handled specially:
- Workspace packages — Symlinked directly to their source directories, not the store
- Workspace dependencies — Can access other workspace packages in the monorepo
- External dependencies — Installed in the isolated store with proper isolation
Comparison with hoisted installs
Aspect | Hoisted (npm/Yarn) | Isolated (pnpm-like) |
---|---|---|
Dependency access | Packages can access any hoisted dependency | Packages only see declared dependencies |
Phantom dependencies | ❌ Possible | ✅ Prevented |
Disk usage | ✅ Lower (shared installs) | ✅ Similar (uses symlinks) |
Determinism | ❌ Less deterministic | ✅ More deterministic |
Node.js compatibility | ✅ Standard behavior | ✅ Compatible via symlinks |
Best for | Single projects, legacy code | Monorepos, strict dependency management |
Advanced features
Peer dependency handling
Isolated installs handle peer dependencies through sophisticated resolution:
# Package with peer dependencies creates specialized paths
node_modules/.bun/package@1.0.0_react@18.2.0/
The directory name encodes both the package version and its peer dependency versions, ensuring each unique combination gets its own installation.
Backend strategies
Bun uses different file operation strategies for performance:
- Clonefile (macOS) — Copy-on-write filesystem clones for maximum efficiency
- Hardlink (Linux/Windows) — Hardlinks to save disk space
- Copyfile (fallback) — Full file copies when other methods aren't available
Debugging isolated installs
Enable verbose logging to understand the installation process:
bun install --linker isolated --verbose
This shows:
- Store entry creation
- Symlink operations
- Peer dependency resolution
- Deduplication decisions
Troubleshooting
Compatibility issues
Some packages may not work correctly with isolated installs due to:
- Hardcoded paths — Packages that assume a flat
node_modules
structure - Dynamic imports — Runtime imports that don't follow Node.js resolution
- Build tools — Tools that scan
node_modules
directly
If you encounter issues, you can:
Switch to hoisted mode for specific projects:
bun install --linker hoisted
Report compatibility issues to help improve isolated install support
Performance considerations
- Install time — May be slightly slower due to symlink operations
- Disk usage — Similar to hoisted (uses symlinks, not file copies)
- Memory usage — Higher during install due to complex peer resolution
Migration guide
From npm/Yarn
# Remove existing node_modules and lockfiles
rm -rf node_modules package-lock.json yarn.lock
# Install with isolated linker
bun install --linker isolated
From pnpm
Isolated installs are conceptually similar to pnpm, so migration should be straightforward:
# Remove pnpm files
rm -rf node_modules pnpm-lock.yaml
# Install with Bun's isolated linker
bun install --linker isolated
The main difference is that Bun uses symlinks in node_modules
while pnpm uses a global store with symlinks.
When to use isolated installs
Use isolated installs when:
- Working in monorepos with multiple packages
- Strict dependency management is required
- Preventing phantom dependencies is important
- Building libraries that need deterministic dependencies
Use hoisted installs when:
- Working with legacy code that assumes flat
node_modules
- Compatibility with existing build tools is required
- Working in environments where symlinks aren't well supported
- You prefer the simpler traditional npm behavior
Related documentation
- Package manager > Workspaces — Monorepo workspace management
- Package manager > Lockfile — Understanding Bun's lockfile format
- CLI > install — Complete
bun install
command reference