Skip to main content
ArcSight

Architecture problems / Circular Dependencies

What are circular dependencies — and why do they block safe refactors?

A circular dependency is a closed loop in the module graph: A depends on B depends on C depends on A. Cycles remove a safe order for changes and testing.

cycleCount > 0 means the graph has closed loops — not every cycle is a crisis, but every cycle is a refactor constraint until you break the smallest edge.

How ArcSight detects this

Many visitors land here from search — not the homepage. Run this workflow locally on your repo.

  1. 1arc impact

    Trace impact on a module inside a cycle before you break an edge. Example path from Nx proof.

    arc impact src/utils/workspace-rootDocs →
  2. 2arc hotspots

    Rank modules by fan-in and downstream reach across the repo.

    arc hotspots
  3. 3arc explain

    Module role and paths in a cyclic graph — what is structurally entangled?

    arc explain src/utils/workspace-root
  4. 4arc watchPro

    Pro: keep architecture clean after merge so this problem does not return.

    arc watchDocs →
  • Run arc scan or arc impact — cycle detection is part of structural analysis output.
  • Inspect cycleCount on repository proofs; non-zero means at least one loop in the scanned graph.
  • Use arc explain on modules in suspected loops to see inbound and outbound paths.

Found the issue?

Use arc impact before you change code — structured blast radius and break paths before merge. Use arc watch (Pro) to stop the problem from returning after you fix it.

All problems · Repository proofs · Install

Why it matters

Circular dependencies answer a different question than fan-in or blast radius: what is structurally entangled? Cycles remove a safe order for changes — you cannot delete, split, or test subsystems confidently until the loop breaks.

What it looks like in codebases

  • Mutual imports between utils and domain layers that grew over time.
  • Barrel files that re-export across package boundaries and close a loop.
  • Plugin systems where core and extension packages depend on each other.

Real repository evidence2 proofs

Every row below comes from an ArcSight analysis snapshot — not a template or keyword page.

Nx

ArcSight detected 100 dependency cycles in this snapshot. Highest fan-in in the cyclic graph: src/utils/workspace-root (fan-in 112). Cycles remove a safe order for refactors until the smallest loop breaks.

ArcSight traced 589 modules and 2,843 edges in Nx (packages/nx).

  • dependency graph100 cycles· structural loops detected
  • src/utils/workspace-rootfan-in 112· CRITICAL risk
  • src/config/nx-jsonfan-in 123· CRITICAL risk
  • src/utils/fileutilsfan-in 71· CRITICAL risk
  • src/config/project-graphfan-in 105· CRITICAL risk
  • src/utils/outputfan-in 102· CRITICAL risk
  • src/utils/versionsblast radius 467· CRITICAL
  • src/nativeblast radius 465· CRITICAL

Inspect first: src/utils/workspace-root · src/config/nx-json · src/utils/fileutils

Full repository proof: /repositories/nx/

Payload CMS

ArcSight detected 100 dependency cycles in this snapshot. Highest fan-in in the cyclic graph: src/types (fan-in 225). Cycles remove a safe order for refactors until the smallest loop breaks.

ArcSight traced 627 modules and 2,704 edges in Payload CMS (packages/payload).

  • dependency graph100 cycles· structural loops detected
  • src/typesfan-in 225· CRITICAL risk
  • srcfan-in 154· CRITICAL risk
  • src/config/typesfan-in 142· CRITICAL risk
  • src/collections/config/typesfan-in 128· CRITICAL risk
  • src/fields/config/typesfan-in 124· CRITICAL risk
  • src/errors/APIErrorblast radius 495· CRITICAL
  • src/versions/typesblast radius 477· CRITICAL

Inspect first: src/types · src · src/config/types

Full repository proof: /repositories/payload/

What to inspect first

  • The shortest cycle involving the module you plan to change.
  • Whether the cycle crosses package or layer boundaries.
  • Shared types or constants that force mutual visibility between modules.

What to do next

  • Break the smallest edge in the cycle first — extract a shared interface module.
  • Re-run impact after each edge removal; partial fixes can hide remaining loops.
  • Hold merge when cycles touch the change surface until arc reports a clean break path.

Install · Validation · Repository proofs