5 min readCalm pace · scan the outline anytime

Strictness ladder

Domain hardest, Application strict, composition root relaxed for wiring, Infrastructure and UI outer.

Strictness ladder

Strictness is not the same for every folder. It starts hardest at Domain and loosens outward. Runtime request flow goes outside → inside; compile-time dependencies point inward.

Concentric rings

Allowed vs forbidden

StrictnessAreaMay importMust not
HardestDomainOwn Domain + Shared kernel portsOther modules, own Application, host framework, ORM, facades/helpers
StrictApplication (Use Cases, App DTOs)Own Domain + Shared kernel portsFacades, ORM, foreign Application/Domain, foreign *ModuleInterface
Relaxed (wiring)Application/ProvidersContainer binds, route registration, config mergeBusiness rules
OuterInfrastructure & UIFramework, ORM, ACL, HTTP clientsLeaking ORM or foreign Domain types into Domain / Use Cases

Dependency rule vs runtime call

ConcernDirectionExample
Runtime requestOutside → inside → outsideController → Use Case → port → adapter → DB
Compile dependencyInner types must not know outer typesDomain does not reference a concrete persistence adapter
Port bindingOuter implements inner interfacePersistence adapter implements OrderRepositoryInterface

Worked examples

StatementLayerVerdict
use …Ordering\Domain\Entities\OrderEntityOrdering Use CaseOK
use …Ordering\Infrastructure\…\OrderRecordOrdering Use CaseForbidden
use …Warehouse\Domain\Ports\Module\WarehouseModuleInterfaceOrdering Use CaseForbidden — use local ACL port
Same WarehouseModuleInterfaceOrdering ACL adapterOK (Infrastructure)
Framework DB facadeOrdering Domain EventForbidden — Shared transaction/dispatcher ports

Composition root exception

Providers (or the host’s equivalent) may wire the framework. If a “rule” appears there, move it to a Use Case or Domain service.

LayerPersistence wording
DomainOrderRepositoryInterface
InfrastructurePersistence adapter implementing the port
Forbidden in Use CasesORM models / query builders / host facades
Illustrative host mappings — not Core MUST

Persistence quarantine (Infrastructure only)

HostTypical place
LaravelEloquent models / repositories under `…/Eloquent/`
SymfonyDoctrine entities / repositories under `…/Doctrine/`
YiiCycle (Yii3) or ActiveRecord (Yii2 brownfield) in Infra
CodeIgniterCI Models / Query Builder only in Infra repositories
CakePHPTable / Entity ORM types quarantined in Infra
SpiralCycle ORM via cycle-bridge in Infra
SlimBring-your-own ORM/SQL — still Infra-only
MezzioBring-your-own (laminas-db, Doctrine, …) — Infra-only

Full topic pages: Adapters overview

Next: golden flow.

Modular Hexagonal Domain-Driven Design
Core 1.0.0-draft