Node.js 2,131 still resolves modules by walking node_modules, so pnpm 69,400 builds that tree in two layers, visible in project a from the previous listing.
cd ~/v5-ch1/store-demo/a
ls -A node_modules | xargs && readlink node_modules/pg
ls node_modules/.pnpm | xargs -n 4
ls node_modules/.pnpm/pg@8.23.0/node_modules | xargs
node -e 'require("pg"); console.log("pg ok")'
node -e 'require("pg-types")' 2>&1 | grep -m1 Error.modules.yaml .pnpm .pnpm-workspace-state-v1.json pg .pnpm/pg@8.23.0/node_modules/pg lock.yaml node_modules pg-cloudflare@1.4.0 pg-connection-string@2.14.0 pg-int8@1.0.1 pg-pool@3.14.0_pg@8.23.0 pg-protocol@1.16.0 pg-types@2.2.0 pg@8.23.0 pgpass@1.0.5 postgres-array@2.0.0 postgres-bytea@1.0.1 postgres-date@1.0.7 postgres-interval@1.2.0 split2@4.2.0 xtend@4.0.2 pg pg-cloudflare pg-connection-string pg-pool pg-protocol pg-types pgpass pg ok Error: Cannot find module 'pg-types'
The top level holds only what package.json declares: one symlink, pg. Everything else lives in the virtual store, node_modules/.pnpm, one folder per version. Inside pg@8.23.0/node_modules/ sit the real pg (hard links into the store) and symlinks to pg's own dependencies, so pg finds pg-types as a sibling while your code finds nothing. The suffix in pg-pool@3.14.0_pg@8.23.0 records a peer dependency: pg-pool is wired to the exact pg it was installed with.
That failed require is the phantom dependency check. Under npm 2,036 's flat layout it would succeed, tying your code to whatever version pg pulled in (Hoisting and Deduplication). For older packages that relied on hoisting, pnpm hoists everything into the hidden node_modules/.pnpm/node_modules, which dependencies can reach but your project cannot, and public-hoist-pattern can expose a package at the top level when a tool insists.