syncpack 15.3.3 lint vs npm-check 6.0.1 on a 12-package npm workspaces fixture: syncpack median 491 ms offline with 21 version mismatches; npm-check --skip-unused median 1.54 s at root (registry).
5 min read
On a 12-package npm workspaces fixture (13 package.json files) with planted version drift, syncpack 15.3.3 lint finished in a median 491 ms offline and exited 1 with 21 mismatch lines. npm-check 6.0.1 --skip-unused took a median 1.54 s at the repo root and 1.59 s on packages/web, because it hits the npm registry for outdated versions.
Short answer: use syncpack when the question is "are our workspace versions consistent?" Use npm-check when the question is "what installed packages are outdated or unused?" They are not drop-in replacements. No affiliate links in this post.
/workspace/bench-syncpack-npm-check/ — root workspaces monorepo with 12 packages under packages/* (web, admin, api, worker, cli, ui, auth, billing, search, notify, analytics, shared). Shared deps intentionally drifted (axios, lodash, zod, react, typescript, eslint, prettier).syncpack 15.3.3, npm-check 6.0.1. Root also had those tools installed so npx resolved locally.npx syncpack lint runs; three npx npm-check --skip-unused --no-emoji runs at repo root; three on packages/web. Wall clock via process.hrtime around the full command.✘ lines across axios/eslint/lodash/prettier/react/typescript/zod. npm-check root median 1542.3 ms (1436 / 1542 / 1598). npm-check packages/web median 1590.2 ms (1554 / 1590 / 1944).syncpack fix / syncpack update, npm-check -u interactive mode, pnpm/yarn catalogs, unused-dep accuracy across TypeScript path aliases, Windows/macOS.| Variant | Median wall | Runs (ms) | Network |
|---|---|---|---|
| syncpack 15.3 lint (13 package.json) | 491 ms | 469 / 477 / 482 / 491 / 491 / 492 / 492 | no |
npm-check 6.0 root --skip-unused | 1542 ms | 1436 / 1542 / 1598 | yes |
npm-check 6.0 packages/web --skip-unused | 1590 ms | 1554 / 1590 / 1944 | yes |
Yes for a CI consistency gate. syncpack only reads package.json files and compares version strings, so it stays under half a second here. npm-check asks registries what is current, so it is slower and the result changes when the registry moves. If you ran npm-check once per workspace package, twelve packages would be tens of seconds before you even fixed anything.
Package-manager choice is a separate decision. The pnpm vs npm vs bun post covers installers; the turbo vs nx post covers monorepo task graphs. This post only covers dependency version hygiene CLIs.
| Job | syncpack lint | npm-check |
|---|---|---|
| Same dependency, different versions across packages | Yes (21 mismatches here) | No |
| Outdated vs latest on the registry | Not in this lint run | Yes |
| Unused dependencies | No | Yes (skipped here with --skip-unused) |
| Works without installing workspace node_modules | Yes | Weak / misleading without installs |
| CI-friendly non-interactive fail | Exit 1 on mismatches | Report only unless you script it |
On this fixture syncpack flagged axios, eslint, lodash, prettier, react, typescript, and zod drift, including exact 4.17.21 vs caret ^4.17.21 lodash rows. npm-check at root reported major upgrades for eslint and typescript among the installed tool tree. On packages/web it reported React, zod, typescript, eslint, and prettier upgrades. Different signals.
If your pain is "why does CI resolve two lodashes?", start with syncpack. If your pain is "what can we bump this month?", start with npm-check or npm-check-updates. The knip vs depcheck post covers unused-export detection, which overlaps npm-check's unused mode but not syncpack.
| Situation | My pick |
|---|---|
| npm workspaces / pnpm / yarn monorepo with version drift | Add syncpack lint to CI; keep an outdated tool separately |
| Single package.json app | syncpack adds little; keep npm-check or ncu |
| You only want interactive "what should I bump" | Stay on npm-check (-u) or use npm-check-updates |
You need workspace: / catalog rules enforced | syncpack |
| You refuse network in CI dependency gates | syncpack lint |
Bottom line: on 12 workspace packages, syncpack lint was about 491 ms offline with 21 actionable mismatches; npm-check was about 1.5 s per target and answered a different question. Who should not "switch": anyone treating these as the same tool — replace nothing, compose them. For TypeScript upgrade timing on the same box, see the TypeScript 7 upgrade post.
How this was made: I generated the 12-package fixture with planted drift, ran syncpack lint and npm-check on the ShopperCove test box, and kept the timing JSON; the write-up was drafted with AI help and checked against that output.
Lab evidence
Hands-on on ShopperCove box 5 Oct 2026 ~23:30-23:32 IST (8 vCPU Intel Xeon / 15 GB shared Linux, Node 20.19.2, npm 9.2.0). Fixture: npm workspaces monorepo, 12 packages under packages/* + root (13 package.json), planted drift on axios/lodash/zod/react/typescript/eslint/prettier. Tools: syncpack 15.3.3, npm-check 6.0.1. Warmups then timed npx wall clocks (process.hrtime). Medians: syncpack lint 490.9 ms (469.4/476.6/482.0/490.9/491.3/491.9/491.9) exit 1 with 21 mismatch lines; npm-check --skip-unused --no-emoji root 1542.3 ms (1435.5/1542.3/1598.0); packages/web 1590.2 ms (1554.3/1590.2/1943.5). Raw: /workspace/bench-syncpack-npm-check/res-syncpack-npm-check.json. Not tested: syncpack fix/update, npm-check -u interactive, pnpm catalogs, Windows/macOS. No affiliate.
Turbo 2.11.7 vs Nx 23.2.1 on 7 packages / 336 JS files: cold median 1177 ms vs 3378 ms (~2.9x). Warm both 7/7 local cache hits (Turbo wall ~138 ms / tool ~16 ms; Nx wall ~668 ms with daemon / tool ~31 ms).
Summary5 Oct 20265 min read
PostgreSQL 14's final supported month is almost here. Dates from postgresql.org.
Summary12 Oct 20261 min read
How the Next.js support policy applies to version 16.
Summary12 Oct 20261 min read