---
title: "Isolated installs"
description: "Strict dependency isolation similar to pnpm's approach"
---

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 (packages importing dependencies they never declared) and makes builds reproducible and deterministic.

Isolated installs are the default for **new** workspace/monorepo projects (with `configVersion = 1` in the lockfile). Existing projects continue using hoisted installs unless explicitly configured.

## 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:

```bash terminal icon="terminal"
# 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` or globally in `$HOME/.bunfig.toml`:

```toml bunfig.toml icon="settings"
[install]
linker = "isolated"
```

### Default behavior

The default linker strategy depends on your project's lockfile `configVersion`:

| `configVersion` | Using workspaces? | Default Linker |
| --------------- | ----------------- | -------------- |
| `1`             | ✅                | `isolated`     |
| `1`             | ❌                | `hoisted`      |
| `0`             | ✅                | `hoisted`      |
| `0`             | ❌                | `hoisted`      |

**New projects**: Default to `configVersion = 1`. In workspaces, v1 uses the isolated linker by default; otherwise it uses hoisted linking.

**Existing Bun projects (made pre-v1.3.2)**: If your existing lockfile doesn't have a version yet, Bun sets `configVersion = 0` when you run `bun install`, preserving the previous hoisted linker default.

**Migrations from other package managers**:

- From pnpm: `configVersion = 1` (using isolated installs in workspaces)
- From npm or yarn: `configVersion = 0` (using hoisted installs)

Override the default by passing the `--linker` flag or setting it in your configuration file.

## How isolated installs work

### Directory structure

Instead of hoisting dependencies, isolated installs create a two-tier structure:

```bash tree layout of node_modules icon="list-tree"
node_modules/
├── .bun/                          # Central package store
│   ├── node_modules/              # Hoisted fallback (see install.hoist)
│   │   └── package -> ../package@1.0.0/node_modules/package
│   ├── 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

1. **Central store** — All packages are installed in `node_modules/.bun/package@version/` directories
2. **Symlinks** — Top-level `node_modules` contains symlinks pointing to the central store
3. **Peer resolution** — Complex peer dependencies create specialized directory names
4. **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

## 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 encode peer dependencies in the store path:

```bash tree layout of node_modules icon="list-tree"
# Package with peer dependencies creates specialized paths
node_modules/.bun/package@1.0.0_react@18.2.0/
```

The directory name includes both the package version and its peer dependency versions, so each unique combination gets its own installation.

### Strict resolution with `install.hoist = false`

By default, Bun creates `node_modules/.bun/node_modules`, a fallback directory with a symlink to every installed package. Because it is an ancestor of every store entry, a package in the store can resolve dependencies it never declared. Set [`install.hoist = false`](/runtime/bunfig#install-hoist) (or `hoist=false` in `.npmrc`, matching pnpm) to skip creating this directory, so undeclared imports fail instead of depending on what else happens to be installed. One caveat, shared with pnpm: the root `node_modules` also sits above the store, so packages linked there (your direct dependencies, `publicHoistPattern` matches, and workspace packages) stay resolvable from any store package:

```toml bunfig.toml icon="settings"
[install]
linker = "isolated"
hoist = false
```

[`install.hoistPattern`](/runtime/bunfig#install-hoistpattern) and [`install.publicHoistPattern`](/runtime/bunfig#install-publichoistpattern) offer pattern-based control over the same fallback directory and the root `node_modules` respectively.

### Global virtual store

When [`install.globalStore`](/runtime/bunfig#install-globalstore) is enabled, store entries are materialized once into a [global virtual store](/pm/global-store) at `<cache>/links/` and `node_modules/.bun/<pkg>@<ver>` is a symlink into it. Warm installs after `rm -rf node_modules` only create one symlink per package instead of copying every package's files again, which is roughly **7× faster** on a typical mid-size project. The global store is **off by default**; see the [global store docs](/pm/global-store) for how to enable it, the full layout, benchmarks, and tradeoffs.

### Backend strategies

When the global store is disabled (the default) or an entry isn't eligible for it, Bun materializes the entry under the project using one of:

- **Clonefile** (macOS) — Copy-on-write filesystem clones
- **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 see what an install is doing:

```bash terminal icon="terminal"
bun install --linker isolated --verbose
```

The verbose output 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:

1. **Switch to hoisted mode** for specific projects:

   ```bash terminal icon="terminal"
   bun install --linker hoisted
   ```

2. **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

```bash terminal icon="terminal"
# 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 is direct:

```bash terminal icon="terminal"
# 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](/pm/workspaces) — Monorepo workspace management
- [Package manager > Lockfile](/pm/lockfile) — Understanding Bun's lockfile format
- [CLI > install](/pm/cli/install) — Complete `bun install` command reference
