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.
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.
