Plate 96
syncpack vs npm-check: Should You Switch? 491ms vs 1.5s
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).
Aditya Challa5 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.
What I tested
- Machine: 8 vCPU Intel Xeon / 15 GB RAM Linux cloud box, Node 20.19.2 / npm 9.2.0, tested 5 Oct 2026 (about 23:30 to 23:32 IST). Shared box; variants timed after warmups.
- Fixture:
/workspace/bench-syncpack-npm-check/— root workspaces monorepo with 12 packages underpackages/*(web, admin, api, worker, cli, ui, auth, billing, search, notify, analytics, shared). Shared deps intentionally drifted (axios, lodash, zod, react, typescript, eslint, prettier). - Tools:
syncpack15.3.3,npm-check6.0.1. Root also had those tools installed sonpxresolved locally. - Timing: seven
npx syncpack lintruns; threenpx npm-check --skip-unused --no-emojiruns at repo root; three onpackages/web. Wall clock viaprocess.hrtimearound the full command. - Findings: syncpack lint median 490.9 ms (469 / 477 / 482 / 491 / 491 / 492 / 492), exit 1, 21
✘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). - One surprise: npm-check on a workspace package still needs network and reports major upgrades (for example React 18 to 19); it does not list cross-package semver drift the way syncpack does.
- Not tested:
syncpack fix/syncpack update, npm-check-uinteractive mode, pnpm/yarn catalogs, unused-dep accuracy across TypeScript path aliases, Windows/macOS.
Is syncpack faster than npm-check?
| 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.
What does each tool actually catch?
| 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.
Should you switch from npm-check to 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.
Sources
- https://syncpack.dev/
- https://github.com/JamieMason/syncpack
- https://www.npmjs.com/package/syncpack
- https://www.npmjs.com/package/npm-check
- https://github.com/dylang/npm-check
- https://docs.npmjs.com/cli/v10/using-npm/workspaces
Related
- https://www.shoppercove.com/blog/pnpm-vs-npm-vs-bun
- https://www.shoppercove.com/blog/turbo-vs-nx
- https://www.shoppercove.com/blog/knip-vs-depcheck
- https://www.shoppercove.com/blog/madge-vs-dependency-cruiser
- https://www.shoppercove.com/blog/typescript-7-should-you-upgrade
- https://www.shoppercove.com/blog/nodejs-26-lts-october-2026-schedule-change
- https://www.shoppercove.com/blog/lefthook-vs-husky
- https://www.shoppercove.com/blog/oxlint-vs-eslint
Lab evidence
What I found running this
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.
Related links
Plate 74
Should You Leave Nx? 3378ms vs 1177ms
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).
5 Oct 2026
Plate 80
size-limit vs bundlesize: Should You Switch? 761ms vs 604ms
size-limit 11.2.0 (@size-limit/file) vs bundlesize 1.0.0-beta.2 on 3 prebuilt dist JS files: brotli median 761 ms vs gzip 604 ms; size-limit gzip mode 621 ms. App reported 57.69 kB brotli / 62.20 kB gzip / 60.74 kB bundlesize gzip.
5 Oct 2026
Plate 45
Should You Leave Depcruise? 679ms Test
Madge 8.0.0 vs dependency-cruiser 16.10.2 on 116 JS files: median wall 679 ms vs 1122 ms (~1.65x). Both found the same 2 circular dependency groups. Depcruise also reported 120 modules / 193 dependencies.
5 Oct 2026