Architecture sprawl is a dependency problem

A backend becomes unmanageable when any change can reach any module through shared tables, utility classes, and informal calls. The antidote is not more folders; it is clear ownership, one-way dependencies, public module interfaces, and tests that make boundary violations visible.

Draw module ownership before folders

  • Group code by business capability before technical layer when the domain is large.
  • A module owns its write model and exposes commands/queries instead of shared-table access.
  • Shared libraries should contain truly stable primitives, not business shortcuts.
  • Cross-module workflows belong in explicit orchestration or events.
  • Architecture tests can forbid imports that violate dependency direction.

Dependency direction that limits blast radius

Requests enter an owning module, which can call stable ports or publish events; other modules do not reach into its internal tables or services.

Diagram

Modules communicate through owned contracts

Requests enter an owning module, which can call stable ports or publish events; other modules do not reach into its internal tables or services.

Growing an orders module without a rewrite

Warning signs of uncontrolled growth

A monthly architecture hygiene check

  • Name the owner of every mutable business entity.
  • Expose module APIs instead of internals.
  • Review dependency direction with automated import rules.
  • Keep shared packages small and stable.
  • Measure coupling by how many modules a change requires, not by folder count.