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.
Aditya Challa4 min read
On a 116-file JavaScript fixture, Madge 8.0.0 took a median 679 ms and dependency-cruiser 16.10.2 took 1122 ms (~1.65x). Both reported the same 2 circular dependency groups I planted. Madge was the faster circular-only check on this tree.
Short answer: leave dependency-cruiser for Madge when you only need a quick circular-import gate. Keep dependency-cruiser when you want a rule engine (custom forbidden edges, severity, metrics) beyond cycle detection. No affiliate links in this post.
What I tested
- Machine: 8 vCPU Intel Xeon / 15 GB RAM Linux cloud box, Node 20.19.2, tested 5 Oct 2026 (about 23:35 to 23:45 IST). Shared box; tools interleaved each round.
- Fixture: 116
.jsfiles undersrc/(layered modules, utils, pages, libs) plus two planted cycles (cycleA → cycleB → cycleC → cycleAandx ↔ y). - Tools:
madge8.0.0 with--circular --extensions js src;dependency-cruiser16.10.2 with a.dependency-cruiser.cjsno-circularrule and--output-type err. (dependency-cruiser 18.x required Node 22+, so 16.10.2 was the Node 20-compatible release used here.) - Timing: one warmup each, then five interleaved warm runs. Median wall-clock of the full CLI call via
perf_counter. - Findings: Madge median 679.023 ms (704 / 679 / 633 / 637 / 703), exit 1, processed 116 files, found 2 circular groups. dependency-cruiser median 1121.753 ms (1122 / 1113 / 1126 / 1156 / 1112), exit 2, cruised 120 modules / 193 dependencies, 2
no-circularerrors matching the same cycles. - One surprise: agreement on the cycles was perfect; the leave-depcruise case on this fixture is speed and simplicity, not detection quality.
- Not tested: TypeScript path mapping, monorepo workspaces, Madge image/graphviz output, dependency-cruiser HTML/metrics reporters in CI, rule sets beyond
no-circular, Windows/macOS, false-positive rates on a production repo.
Is Madge faster for circular checks?
| Tool | Median | Runs (ms) | Files / modules | Circular groups |
|---|---|---|---|---|
| Madge 8.0.0 | 679 ms | 704 / 679 / 633 / 637 / 703 | 116 files | 2 |
| dependency-cruiser 16.10.2 | 1122 ms | 1122 / 1113 / 1126 / 1156 / 1112 | 120 modules, 193 deps | 2 |
On this fixture Madge finished about 1.65x faster and named the same two cycles. If your only CI question is "are there circular imports?", Madge answered it with less wall time here.
Circular checks sit next to unused-code and lint gates. The Knip vs depcheck post covers unused files and exports; the Biome vs ESLint + Prettier post and the oxlint vs ESLint post cover lint/format. This post is only the dependency-graph circular decision.
What do you lose leaving dependency-cruiser?
dependency-cruiser is a configurable rules engine. You lose custom forbidden/orphan rules, severity levels, cruise metrics, and richer reporters if you switch to Madge for cycles only. Teams that encode architecture boundaries as depcruise rules should not drop it because of a 1.65x circular-scan delta.
Also note the Node version floor. dependency-cruiser 18.x wanted Node 22+ on this box; pinning 16.10.2 kept the lab on Node 20. Re-check the engine range before you upgrade either tool in CI.
Should you leave dependency-cruiser for Madge?
| Situation | My pick |
|---|---|
| CI only fails on circular imports | Prefer Madge; re-measure your tree |
| You maintain custom forbidden-edge rules | Stay on dependency-cruiser |
| You want one tool for cycles + architecture metrics | Stay on dependency-cruiser |
| You already run Knip/depcheck for unused code and only need a cycle gate | Madge is the lighter add-on to try |
| Graphviz image reports are part of review | Madge still fits; compare output needs separately |
Bottom line: on 116 JS files, Madge median was 679 ms and dependency-cruiser was 1122 ms, and both found the same 2 cycles. Who should not switch yet: teams that rely on dependency-cruiser's rule engine. Everyone else gating only on circular imports should time both on their own tree.
How this was made: I built the fixture with planted cycles, ran interleaved Madge and dependency-cruiser 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://github.com/pahen/madge
- https://www.npmjs.com/package/madge
- https://github.com/sverweij/dependency-cruiser
- https://www.npmjs.com/package/dependency-cruiser
- https://github.com/sverweij/dependency-cruiser/blob/main/doc/rules-reference.md
Related
- https://www.shoppercove.com/blog/knip-vs-depcheck
- https://www.shoppercove.com/blog/biome-vs-eslint-prettier
- https://www.shoppercove.com/blog/oxlint-vs-eslint
- https://www.shoppercove.com/blog/eslint-10-12-release-october-2026
- https://www.shoppercove.com/blog/dprint-vs-prettier
- https://www.shoppercove.com/blog/pnpm-vs-npm-vs-bun
- https://www.shoppercove.com/blog/typescript-7-should-you-upgrade
- https://www.shoppercove.com/blog/jest-vs-vitest
Lab evidence
What I found running this
Hands-on on ShopperCove box 5 Oct 2026 ~23:35-23:45 IST (8 vCPU Intel Xeon / 15 GB shared Linux, Node 20.19.2). Fixture: 116 JS files under src/ with two planted cycles (A→B→C→A and x↔y). Versions: madge 8.0.0 (--circular --extensions js src); dependency-cruiser 16.10.2 (Node-20-compatible; 18.x required Node 22+) with no-circular rule. Wall medians (5 interleaved after warmup): madge 679.023 ms (704.457/679.023/633.036/636.634/703.219); depcruise 1121.753 ms (1121.753/1112.724/1125.972/1156.23/1112.005). Both found 2 circular groups; depcruise also reported 120 modules / 193 dependencies. Raw: /workspace/bench-madge/res-madge.json. Not tested: TS path mapping, monorepo workspaces, non-circular rule sets, HTML reporters, Windows/macOS, production false-positive rates. No affiliate.
Related links
Plate 31
Should You Leave Rollup? 964ms vs 246ms
Rolldown 1.2.12 vs Rollup 4.64.0 on 501 ESM files (197380 B source): median wall 245.617 ms vs 964.3 ms (~3.9x). Output 130522 vs 126894 B. Direct node bin, 5 interleaved warm runs, no minify.
5 Oct 2026
Plate 94
Should You Leave Prettier? 1.59s vs 0.51s
dprint 0.60.1 vs Prettier 3.9.9 on 180 files (120 JS + 40 JSON + 20 MD, 38925 B pristine): write medians 514 ms vs 1586 ms; check 455 ms vs 1313 ms. Output 44805 vs 45285 B. All 120 JS files differed on arrow-param parentheses under these defaults.
5 Oct 2026
Plate 74
Should You Leave Terser? 824ms vs 41ms
Terser 5.51.2 vs esbuild 0.28.2 vs SWC 1.16.13 minify on a 403,418-byte unminified ESM bundle (800 modules): medians 824 ms / 41 ms / 70 ms. Output sizes 219492 / 207619 / 199712 B. Leave Terser if you only need fast minify; keep it for Terser-only compress options.
5 Oct 2026