pnpm 9 Workspaces: The Best Monorepo Package Manager in 2026
pnpm 9 introduces Catalogs for shared dependency versions and strict symlink node_modules that prevent phantom dependencies - here is the complete workspaces setup guide.
Content-addressable store - each version of a package is stored once globally, referenced by symlink. A monorepo with 10 apps sharing React doesn't store 10 copies of React.
Strict node_modules - packages can only import what is in their own package.json. Phantom dependencies (importing a package that happens to be installed by a sibling) cause runtime errors rather than silently working.
Catalogs - new in v9, define shared dependency versions at the workspace root to keep all packages in sync.
Update all packages at once: change the version in pnpm-workspace.yaml and run pnpm install.
Common Workspace Commands
# Install all workspace dependencies
pnpm install
# Add a dependency to a specific package
pnpm --filter web add react-query
# Add a shared devDependency to the root
pnpm add -D -w typescript
# Run build in all packages
pnpm -r run build
# Run build in all packages in dependency order
pnpm -r --workspace-concurrency=4 run build
# Run only in packages with changes (combine with Turborepo)
pnpm --filter "...[origin/main]" run build
# Run in a specific package
pnpm --filter web run dev
pnpm patch for Patching Dependencies
When a package has a bug and no fix is released yet:
# Create a patch
pnpm patch some-package@1.2.3
# Edit the files in the temp directory it creates
# Then apply the patch
pnpm patch-commit /path/to/temp-dir
This creates a .patches/some-package@1.2.3.patch file and adds it to pnpm-workspace.yaml:
pnpm deploy creates a standalone deployment directory with only the production dependencies for one package:
FROM node:22-alpine AS base
RUN npm install -g pnpm@9
FROM base AS builder
WORKDIR /app
COPY . .
RUN pnpm install --frozen-lockfile
RUN pnpm --filter web build
FROM base AS runner
WORKDIR /app
# Deploy only web's production deps - no dev deps, no other packages
COPY --from=builder /app .
RUN pnpm deploy --filter=web --prod /deploy/web
FROM node:22-alpine AS final
WORKDIR /app
COPY --from=runner /deploy/web .
COPY --from=builder /app/apps/web/.next .next
CMD ["node", "server.js"]
Strict vs Hoisted Mode
pnpm's default (strict) prevents packages from accessing unlisted dependencies. If you have legacy code that relies on hoisted deps:
Practical deep-dives on LLMs, developer tools, and AI engineering. No filler. Unsubscribe any time.
// written byFIG. AUTH-01
538
Mahmudul Haque Qudrati
CEO & ML Engineer
CEO and ML Engineer at Pristren. Builds AI-powered software for teams and writes about machine learning, LLMs, developer tools, and practical AI applications.
What Is Alibaba Banning Claude Code Over Backdoor Risks? A Practical Overview
Alibaba is reportedly banning Claude Code from its workplace due to alleged backdoor risks. This post explains the incident, the technical concerns, and the broader implications for AI coding assistants in regulated environments.