pnpm 10 📦 Offline Mode and Caching Best Practices in pnpm
pnpm’s offline capabilities are a direct consequence of its content-addressable store architecture. Every package file that pnpm has ever downloaded is stored once in a global directory. When you run pnpm install --offline, pnpm does not contact the registry. It resolves the dependency tree from the lockfile, locates the required files in the store, and hard-links them into the project’s virtual store. If a package is missing from the store, the install fails immediately with ERR_PNPM_NO_OFFLINE_META rather than attempting a network request . This makes offline installs deterministic, but it also means that the store must be fully populated before the offline install begins. The exam tests the distinction between the store (the files) and the metadata cache (the registry index used for resolution), because an offline install can fail even when the files are present if the metadata needed to resolve a version range is missing .
Key point: --offline forces pnpm to use only what is already in the store. --prefer-offline skips staleness checks for cached data but still requests missing data from the server. The store contains package files; the metadata cache contains registry information. Both must be populated for a fully offline install to succeed.
Why offline mode and caching matter
The air-gapped environment problem. Production servers, CI runners, and security-sensitive environments often have no outbound network access. The registry is unreachable, but the build must still run. pnpm solves this by allowing the store to be copied to the target environment. With the lockfile and the store present, pnpm install --offline reconstructs the dependency tree without a single network request .
The metadata-versus-files problem. The store is not a complete offline solution on its own. When package.json contains a version range like ^19.0.0, pnpm must resolve that range to a specific version. The resolution requires registry metadata, which pnpm caches separately in ~/.cache/pnpm/metadata. If the metadata cache is missing, pnpm install --offline fails with ERR_PNPM_NO_OFFLINE_META, even if the package files are in the store . The fix is to populate the metadata cache before going offline, either by running a normal install or by running pnpm store add <package> to fetch the metadata and files together.
The reproducibility problem. An offline install is only as reproducible as the lockfile. If the lockfile is committed and the store is populated with the exact versions it references, the install produces the same dependency tree on every machine. The --frozen-lockfile flag prevents pnpm from modifying the lockfile during the install, which is the correct behavior for CI and production .
The read-only store problem. pnpm 11.7 introduced --frozen-store for environments where the store is on a read-only filesystem (Nix store, read-only bind mount, OCI image layer). When enabled, pnpm opens the store index in immutable mode and refuses to write to the store. If a package requires a build step (native module compilation) and the build output is not already in the store, the install fails with ERR_PNPM_FROZEN_STORE_NEEDS_BUILD instead of attempting to write .
The trade-off. Offline installs require preparation: the store must be populated, the metadata cache must be warm, and the lockfile must be accurate. This preparation is the cost of determinism. For environments with reliable network access, --prefer-offline offers a middle ground: it skips the staleness check on cached data and only contacts the registry if a package is missing .
a. Populating the store and metadata cache
The store and the metadata cache are separate. The store lives at the path returned by pnpm store path. The metadata cache lives under the pnpm cache directory, which is typically ~/.cache/pnpm/metadata.
# Check the store location
pnpm store path
# Output: /home/user/.local/share/pnpm/store/v10
# Check the cache directory
pnpm config get cache-dir
# Output: /home/user/.cache/pnpm
To populate both, run a normal install. The install downloads the package files into the store and the registry metadata into the cache.
# Normal install populates store and metadata cache
pnpm install
If you need to add a specific package to the store without a full install, pnpm store add <package> fetches the package and its metadata. This is useful for pre-populating the store in a build step that runs before the offline environment is sealed .
# Add a package to the store and cache
pnpm store add @types/react
The pnpm store prune command removes unreferenced packages from the store. It does not remove metadata from the cache. For a fully offline environment, do not run prune after the store has been populated.
b. Running an offline install
The --offline flag forces pnpm to use only local resources. If a package or its metadata is missing, the install fails.
# Fully offline install
pnpm install --offline
For environments where the lockfile must not change, combine --offline with --frozen-lockfile.
# Offline install with immutable lockfile
pnpm install --offline --frozen-lockfile
For read-only stores, pnpm 11.7+ adds --frozen-store. This flag requires Node.js 22.15.0 or later, or 23.11.0/24.0.0 for the read-only store opening capability .
# Read-only store, fully offline, immutable lockfile
pnpm install --frozen-store --offline --frozen-lockfile
The --prefer-offline flag is the opposite of --offline. It skips the staleness check for cached metadata but still fetches missing data from the server. It is useful when you want to avoid unnecessary network requests for data that is already cached, but you cannot guarantee that the cache is complete.
# Use cached data when available, fetch missing data
pnpm install --prefer-offline
c. Copying the store to a production environment
The official pnpm documentation describes two production bootstrap methods. The first is the recommended one: commit the lockfile and run pnpm install with network access. The second is for air-gapped environments: commit the lockfile, copy the package store to the production environment, and run pnpm install --offline .
# On the source machine, determine the store path
pnpm store path
# Copy the store to the target machine
# (use rsync, tar, or the deployment mechanism)
rsync -av /home/user/.local/share/pnpm/store/v10/ target:/path/to/store/
# On the target machine, configure pnpm to use the copied store
pnpm config set store-dir /path/to/store
# Run the offline install
pnpm install --offline --frozen-lockfile
The store-dir setting can be configured in .npmrc or via the --store-dir flag. The target machine must have the same pnpm version and the same lockfile for the store to be compatible.
Complete Example Session
# ============================================
# PART 1: CHECK STORE AND CACHE LOCATIONS
# ============================================
pnpm store path
# /home/user/.local/share/pnpm/store/v10
pnpm config get cache-dir
# /home/user/.cache/pnpm
# ============================================
# PART 2: POPULATE STORE AND CACHE
# ============================================
pnpm install
# Downloads packages to store and metadata to cache.
# ============================================
# PART 3: VERIFY METADATA CACHE
# ============================================
ls ~/.cache/pnpm/metadata-v1.3/registry.npmjs.org/
# @types, express, lodash, ...
# ============================================
# PART 4: RUN OFFLINE INSTALL
# ============================================
rm -rf node_modules
pnpm install --offline
# Succeeds: all packages and metadata are local.
# ============================================
# PART 5: TEST FAILURE MODE
# ============================================
pnpm cache delete @types/react
rm -rf node_modules
pnpm install --offline
# ERR_PNPM_NO_OFFLINE_META
# Metadata for @types/react is missing.
# ============================================
# PART 6: REPOPULATE AND RETRY
# ============================================
pnpm store add @types/react
pnpm install --offline
# Succeeds: metadata and files are now present.
# ============================================
# PART 7: PREFER-OFFLINE MODE
# ============================================
pnpm install --prefer-offline
# Uses cache when available, fetches missing data.
# ============================================
# PART 8: COPY STORE TO TARGET
# ============================================
rsync -av $(pnpm store path)/ target:/opt/pnpm-store/
pnpm config set store-dir /opt/pnpm-store
pnpm install --offline --frozen-lockfile
# ============================================
# PART 9: READ-ONLY STORE (PNPM 11.7+)
# ============================================
pnpm install --frozen-store --offline --frozen-lockfile
# Fails with ERR_PNPM_FROZEN_STORE_NEEDS_BUILD
# if a package requires a build not in the store.
The nine parts trace the offline workflow: checking locations, populating the store and cache, verifying the metadata cache, running an offline install, observing the failure mode when metadata is missing, repopulating, using prefer-offline, copying the store to a target machine, and the read-only store flag.
Quick Reference
Offline Flags
| Flag | Effect |
|---|---|
--offline | Use only local store and metadata; fail if missing |
--prefer-offline | Use cache, fetch missing data from server |
--frozen-lockfile | Do not modify lockfile |
--frozen-store | Read-only store (pnpm 11.7+) |
Store and Cache Commands
| Command | Purpose |
|---|---|
pnpm store path | Show store location |
pnpm store add <pkg> | Add package to store and metadata cache |
pnpm store prune | Remove unreferenced packages |
pnpm config get cache-dir | Show metadata cache location |
Production Bootstrap
| Method | Steps |
|---|---|
| Recommended | Commit lockfile, pnpm install with network |
| Air-gapped | Commit lockfile, copy store, pnpm install --offline |
Best Practices
✅ Do This:
pnpm install --offline --frozen-lockfile
<!-- Offline install with immutable lockfile --> # ✅
pnpm store add <pkg>
<!-- Pre-populate store and metadata --> # ✅
rsync -av $(pnpm store path)/ target:/opt/pnpm-store/
<!-- Copy the full store to the target --> # ✅
❌ Don’t Do This:
# Run pnpm store prune before sealing the environment
<!-- Removes packages that may be needed later --> # ❌
# Assume the store alone is sufficient for offline
<!-- Metadata cache is also required --> # ❌
# Use --offline in an environment with missing metadata
<!-- Fails with ERR_PNPM_NO_OFFLINE_META --> # ❌
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
ERR_PNPM_NO_OFFLINE_META | Metadata cache missing | Run pnpm store add or normal install |
ERR_PNPM_FROZEN_STORE_NEEDS_BUILD | Build output missing from read-only store | Pre-build packages before sealing store |
| Offline install succeeds but node_modules empty | Store path misconfigured | Verify store-dir setting |
--prefer-offline still contacts registry | Missing package in store | Use --offline for strict mode |
| Store copy incompatible | Different pnpm version or lockfile | Match versions exactly |
Real-World Examples
1. Check Store Path
pnpm store path
2. Check Cache Directory
pnpm config get cache-dir
3. Populate Store
pnpm install
4. Add Single Package to Store
pnpm store add lodash
5. Offline Install
pnpm install --offline
6. Offline Immutable Install
pnpm install --offline --frozen-lockfile
7. Prefer-Offline Mode
pnpm install --prefer-offline
8. Copy Store
rsync -av $(pnpm store path)/ target:/opt/pnpm-store/
9. Set Store Directory
pnpm config set store-dir /opt/pnpm-store
10. Read-Only Store (pnpm 11.7+)
pnpm install --frozen-store --offline --frozen-lockfile
Visual
Store vs Metadata Cache
┌──────────────────────────────────────────────┐
│ STORE (pnpm store path) │
│ ├── Package files (content-addressable) │
│ ├── Hard-linked into projects │
│ └── Required for installation │
└──────────────────┬───────────────────────────┘
│
│ Both are required
│ for --offline
▼
┌──────────────────────────────────────────────┐
│ METADATA CACHE (pnpm config get cache-dir) │
│ ├── Registry index (version ranges) │
│ ├── Used for resolution │
│ └── Required for version resolution │
└──────────────────────────────────────────────┘
The store has the files. The cache has the version information. Offline mode needs both.
Offline Install Flow
┌──────────────────────────────────────────────┐
│ pnpm install --offline │
└──────────────────┬───────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ Read lockfile → exact versions │
└──────────────────┬───────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ Check metadata cache for resolution │
│ ├─ Missing → ERR_PNPM_NO_OFFLINE_META │
│ └─ Present → continue │
└──────────────────┬───────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ Check store for package files │
│ ├─ Missing → ERR_PNPM_NO_OFFLINE │
│ └─ Present → hard-link into project │
└──────────────────┬───────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ Install completes without network │
└──────────────────────────────────────────────┘
Every step must pass. The store and the cache are both prerequisites.
Summary
| Item | Value |
|---|---|
| Offline flag | --offline |
| Prefer-offline flag | --prefer-offline |
| Read-only store flag | --frozen-store (pnpm 11.7+) |
| Store location | pnpm store path |
| Metadata cache location | pnpm config get cache-dir |
| Populate store | pnpm install or pnpm store add <pkg> |
| Production bootstrap | Commit lockfile + copy store + --offline |
Key takeaways:
--offlineuses only local resources. The store must contain the package files, and the metadata cache must contain the registry information needed for resolution. If either is missing, the install fails .- The store and the metadata cache are separate. The store holds files. The cache holds version resolution data. A fully populated store without a metadata cache still fails with
ERR_PNPM_NO_OFFLINE_META. pnpm store addpopulates both. It fetches the package files and the metadata in one command, making it the tool for pre-seeding an offline environment.--prefer-offlineis the middle ground. It skips staleness checks for cached data but fetches missing packages from the server. It is not a true offline mode.- For air-gapped production, copy the store. The official documentation recommends committing the lockfile and copying the store, then running
pnpm install --offline. - Read-only stores require
--frozen-store. Introduced in pnpm 11.7, this flag opens the store index in immutable mode and fails early if a build is needed but not present .
Remember: Offline mode is not a single flag. It is a preparation discipline: populate the store, warm the metadata cache, commit the lockfile, and copy the store to the target. The --offline flag enforces the discipline by failing when the preparation is incomplete. For environments with network access, --prefer-offline avoids unnecessary requests without the risk of a failed install.
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!