--- title: "Global cache" description: "How Bun stores and manages packages in its global cache" --- Bun stores every package downloaded from the registry in a global cache at `~/.bun/install/cache`, or the path set by the `BUN_INSTALL_CACHE_DIR` environment variable. Packages live in subdirectories named like `${name}@${version}`, so Bun can cache multiple versions of a package. ```toml bunfig.toml icon="settings" [install.cache] # the directory to use for the cache dir = "~/.bun/install/cache" # when true, don't load from the global cache. # Bun may still write to node_modules/.cache disable = false # when true, always resolve the latest versions from the registry disableManifest = false ``` --- ## Minimizing re-downloads When installing a package, if the cache already contains a version in the range specified by `package.json`, Bun uses the cached copy instead of downloading it again. If the semver version has a pre-release suffix (`1.0.0-beta.0`) or a build suffix (`1.0.0+20220101`), Bun replaces the suffix with a hash of that value instead, to reduce the chance of errors from long file paths. When the `node_modules` folder exists, before installing, Bun checks that `node_modules` contains all expected packages with appropriate versions. If so, `bun install` completes. Bun uses a custom JSON parser which stops parsing as soon as it finds `"name"` and `"version"`. If a package is missing or has a version incompatible with the `package.json`, Bun checks for a compatible module in the cache. If the cache has one, Bun installs it into `node_modules`. Otherwise, Bun downloads the package from the registry, then installs it. --- ## Fast copying Once a package is downloaded into the cache, Bun still needs to copy those files into `node_modules`. It uses the fastest syscalls available for this: hardlinks on Linux and Windows, `clonefile` on macOS. --- ## Saving disk space On Linux and Windows, Bun uses hardlinks to "copy" a module into a project's `node_modules` directory, so the contents of the package only exist in a single location on disk. This greatly reduces the disk space used by `node_modules`. The same applies on macOS, with a caveat. There Bun uses `clonefile`, which is copy-on-write: the clone occupies no extra disk space, but it counts towards the drive's limit. Because the copy only happens on write, patching `node_modules/*` in one project can't affect other installations. Configure this with the `--backend` flag, which all of Bun's package management commands respect. - **`hardlink`**: Default on Linux and Windows. - **`clonefile`**: Default on macOS. - **`clonefile_each_dir`**: Similar to `clonefile`, except it clones each file individually per directory. It is only available on macOS and tends to perform slower than `clonefile`. - **`copyfile`**: The fallback used when any of the above fail. It is the slowest option. On macOS, it uses `fcopyfile()`; on Linux it uses `copy_file_range()`. - **`symlink`**: Symlinks each file instead of copying it. Only hoisted installs use it: `--backend=symlink` applies it to every package (macOS and Linux; Windows ignores the flag); without the flag, Bun uses it only for `file:` dependencies outside the project directory (for example `file:../foo`) and for transitive `file:` dependencies. If you install with `--backend=symlink`, Node.js doesn't resolve node_modules of dependencies unless each dependency has its own `node_modules` folder or you pass `--preserve-symlinks` to `node`. See [Node.js documentation on `--preserve-symlinks`](https://nodejs.org/api/cli.html#--preserve-symlinks). ```bash terminal icon="terminal" bun install --backend symlink node --preserve-symlinks ./foo.js ``` Bun's runtime also supports `--preserve-symlinks`.