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.
4 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.
.js files under src/ (layered modules, utils, pages, libs) plus two planted cycles (cycleA → cycleB → cycleC → cycleA and x ↔ y).madge 8.0.0 with --circular --extensions js src; dependency-cruiser 16.10.2 with a .dependency-cruiser.cjs no-circular rule and --output-type err. (dependency-cruiser 18.x required Node 22+, so 16.10.2 was the Node 20-compatible release used here.)perf_counter.no-circular errors matching the same cycles.no-circular, Windows/macOS, false-positive rates on a production repo.| 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.
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.
| 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.
Lab evidence
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.
Playwright 1.55.1 Chromium vs Cypress 14.5.4 Electron on one local smoke (visit /, assert h1, click, assert). Warm medians (7 rounds after 1 warm-up): Playwright 1,466 ms vs Cypress 4,243 ms (~2.9x). Disk: PW node_modules ~12 MB + cache ~918 MB; Cypress node_modules ~23 MB + cache ~601 MB. Fixture /workspace/bench-pw-cy/.
Hands-on6 Oct 20264 min read
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.
Summary5 Oct 20264 min read
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.
Summary5 Oct 20265 min read