Acyclic Dependencies Principle

No Change
adopt
First Added:June 25, 2026 Updated: June 26, 2026

Acyclic Dependencies Principle

The Acyclic Dependencies Principle (ADP) forbids cycles in the component dependency graph. Package A may depend on B, but no chain of dependencies may loop back to A. We adopt it in monorepos, modular monoliths, and multi-service estates where circular imports block builds or force big-bang releases. Break cycles with Dependency Inversion Principle seams or event boundaries before layering rules fail in production.

Blurb

Allow no cycles in the component dependency graph.

Summary

What it is: A coupling rule for components (packages, modules, libraries, deploy units). The dependency graph must be a directed acyclic graph (DAG). Cycles force mutual rebuilds and hide a clear build or release order.

Why it matters: Circular dependencies make incremental change expensive. A tweak in one module ripples through the cycle. Tests and deploys cannot isolate a single component. Teams co-own tangled code because ownership follows the cycle.

Source: Martin states the rule in Clean Architecture as “allow no cycles in dependencies.”

Breaking cycles: Dependency Inversion Principle is the primary tool: extract an abstraction, move it to a third package, and invert the dependency so both sides depend on the interface.

When to use: Package dependency reviews, monorepo lint rules, and architecture checks before extract-to-library refactors. Apply when build tools or import graphs already show back-edges between modules.

When to pull back: Tiny single-package apps with no module boundaries. Do not invent package splits solely to satisfy a linter when there is no real component graph.

Relation to siblings: Stable Dependencies Principle and Stable Abstractions Principle govern how acyclic edges should point (toward stability and abstraction). ADP is the prerequisite: fix cycles first, then aim dependency direction.

Details

Component Coupling Context

ADP is one of three classic component coupling principles (Robert C. Martin). Siblings are Stable Dependencies Principle (SDP) and Stable Abstractions Principle (SAP).

PrincipleGist
ADPNo cycles in the component graph
SDPDepend toward more stable components (Stable Dependencies Principle)
SAPStable components stay abstract (Stable Abstractions Principle)

Breaking Cycles (Practical)

TechniqueWhen it fits
Extract shared interface to a third packageTwo modules need each other’s types
Dependency Inversion Principle (preferred)High-level module should not depend on low-level detail; extract shared interface
Event or message boundaryRuntime decoupling when compile-time inversion is awkward
Merge componentsCycle means the split was wrong; reunify

Practical Signs

SignalLikely fix
Build order only works with hacks or --forceMap imports; break the smallest back-edge
common imports from features and vice versaInvert dependency or extract shared kernel
Microservices call each other synchronously in a ringIntroduce events or consolidate ownership
Refactor blocked because “everything depends on everything”ADP review before more features

Common Failure Modes

  • Ignoring test-only or devDependency cycles that mirror production cycles
  • Breaking a cycle by moving code to a junk-drawer shared package (creates a god module)
  • Layer rules on paper while code imports whatever is convenient
  • Splitting services without removing synchronous call loops

Related Garden Items