ADR-0006: pnpm for Package Management¶
Status: Accepted Date: 2024-12-01 (Estimated) Deciders: GetCimple Team Tags:
tooling,developer-experience,monorepo
Context¶
GetCimple is structured as a monorepo with multiple packages (apps, shared libraries, docs). We need a package manager that handles:
Requirements: - Monorepo workspace support - Fast installation and dependency resolution - Disk space efficiency (multiple projects, node_modules can be huge) - Lock file for reproducible builds - Compatible with GitHub Actions CI/CD
Constraints: - 3-person team (simple tooling preferred) - Monorepo structure: apps/, packages/, docs/ - Must work with Vite, React, MkDocs build processes - No additional cost
Options Considered¶
Option A: pnpm¶
Description: Fast, disk space-efficient package manager with native monorepo support.
Pros: - β Disk efficiency: Uses content-addressable storage (saves GB with multiple projects) - β Fast: Faster than npm and yarn (especially fresh installs) - β Monorepo native: Workspace support built-in (pnpm-workspace.yaml) - β Strict dependencies: Prevents phantom dependencies (only declared deps accessible) - β Lock file: pnpm-lock.yaml ensures reproducible builds - β Compatible: Works with all npm packages - β Growing adoption: Used by Vue, Vite, and other major projects
Cons: - β Less common than npm (some developers unfamiliar) - β Slightly different CLI from npm (pnpm add vs npm install) - β Some edge case compatibility issues with older packages
Estimated Effort: 1 hour to switch from npm
Option B: npm (default)¶
Description: Node.js default package manager.
Pros: - β Everyone knows it - β No installation required - β Works everywhere - β Workspaces support (npm 7+)
Cons: - β Slow: Slowest of the three options - β Disk space: Duplicates node_modules across workspace packages - β Phantom deps: Allows importing undeclared dependencies (risky) - β Large lock file
Estimated Effort: Already using (no switch needed)
Option C: Yarn (v3/v4 Berry)¶
Description: Alternative package manager with Plug'n'Play mode.
Pros: - β Fast (comparable to pnpm) - β Yarn workspaces mature - β Plug'n'Play mode (no node_modules)
Cons: - β Plug'n'Play compatibility issues with some tools - β More complex than pnpm - β Larger lock file than pnpm - β Zero-installs feature controversial
Estimated Effort: 2-3 hours to configure Plug'n'Play properly
Decision¶
We chose: Option A - pnpm
Rationale: 1. Monorepo optimized: Native workspace support, perfect for our apps/ and packages/ structure 2. Disk space: Content-addressable storage saves gigabytes (important with MkDocs, React, multiple apps) 3. Speed: 2-3x faster than npm for fresh installs (CI/CD runs faster) 4. Strict dependencies: Prevents phantom dependency bugs (quality improvement) 5. Future-proof: Growing adoption, momentum in ecosystem 6. Simple migration: Compatible with npm, easy to switch
Key Trade-offs Accepted: - We're accepting slightly less familiarity (pnpm vs npm) for performance and disk savings - We're accepting potential edge case issues (very rare) for strictness benefits
Consequences¶
Positive¶
- β Faster CI/CD: GitHub Actions runs 30-50% faster (fewer npm install minutes)
- β Disk savings: ~2-3GB saved vs npm across all projects and node_modules
- β Monorepo clarity: pnpm-workspace.yaml makes package relationships explicit
- β Dependency hygiene: Phantom dependency bugs prevented (builds fail if deps not declared)
- β Reproducible builds: pnpm-lock.yaml ensures consistent dependency versions
Negative¶
- β οΈ Onboarding: New team members may need 5-minute pnpm intro
- β οΈ CLI differences: Must use
pnpm addnotnpm install(easy to learn) - β οΈ Edge cases: Very rare package incompatibilities (can use shamefully-hoist as escape hatch)
Risks¶
| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
| Package incompatibility | LOW | LOW | Use .npmrc shamefully-hoist option; fall back to npm for specific packages |
| Team forgets pnpm commands | LOW | LOW | Add package.json scripts (pnpm dev β npm run dev works); document in README |
| pnpm abandoned by maintainers | LOW | MEDIUM | Growing adoption reduces risk; can migrate back to npm if needed (low effort) |
Compliance Note¶
ACSC Essential 8 Impact: - Relevant Control: Application Control (Maturity Level 1-2) - Dependency integrity: pnpm's strict mode prevents undeclared dependencies - Supply chain security: Content-addressable storage provides integrity verification
Australian Data Residency: - Not applicable: Package manager is local tooling
Audit Trail: - pnpm-lock.yaml tracked in Git provides full dependency audit trail - Reproducible builds support compliance verification
Implementation Notes¶
Prerequisites:
- Node.js 18+ installed
- pnpm installed globally (npm install -g pnpm@latest)
Integration Points: - GitHub Actions: Use pnpm/action-setup@v2 for CI/CD - Vite: Works seamlessly with pnpm - Monorepo: pnpm-workspace.yaml defines workspace packages
Configuration:
Monitoring: - CI/CD build times (expect 30-50% faster vs npm) - Disk usage savings (track node_modules size)
Documentation Updates Needed: - β README.md updated with pnpm commands - β Development guide uses pnpm - β GitHub Actions workflows use pnpm
Revisit¶
Revisit By: N/A (low-risk decision, no planned revisit) Blast Radius: LOW - Easy to switch back to npm if needed (1-2 hours)
Conditions for Revisit: - Widespread compatibility issues (>5 packages requiring workarounds) - pnpm project loses momentum (maintainer departure, no updates) - npm releases features that eliminate pnpm advantages
Next Review: N/A (only revisit if problems arise)
References¶
Version History¶
| Version | Date | Author | Changes |
|---|---|---|---|
| 1.0 | 2025-10-20 | Claude | Initial ADR capturing historical decision |