Clean Architecture vs Hexagonal vs DDD: The Differences
These terms describe overlapping ideas, and most of the confusion is vocabulary. Here is what each one actually contributes, why DDD is not an architecture, and what you are really choosing.
Clean Architecture, hexagonal architecture, onion architecture and Domain-Driven Design come up in the same discussions, and it is easy to think you have to pick one. Mostly you do not: three of them are the same core idea with different vocabulary, and the fourth is a different kind of thing entirely. This untangles them.
The rule they share
Hexagonal, Clean and onion architecture all enforce one rule: dependencies point inward, toward your business logic, never outward toward frameworks, databases or transport. Your domain code does not import Eloquent, does not know it is behind HTTP, and can be tested without a database. Everything external plugs in at the edges through interfaces the domain defines. That rule is the whole point; the diagrams are just ways of drawing it.
What each one adds
| Name | Origin | Specific contribution | Vocabulary |
|---|---|---|---|
| Hexagonal (ports and adapters) | Alistair Cockburn, 2005 | Frames the boundary as ports (interfaces) and adapters (implementations); symmetric, no inside/outside hierarchy | Port, adapter, driving side, driven side |
| Onion architecture | Jeffrey Palermo, 2008 | Draws it as concentric layers with the domain model at the centre | Domain model, domain services, application services, infrastructure |
| Clean Architecture | Robert C. Martin, 2012 | Consolidates the above into one diagram, adds the dependency rule and named roles | Entities, use cases, interface adapters, frameworks and drivers |
| DDD | Eric Evans, 2003 | Not an architecture: a way to model the business and structure teams around it | Bounded context, aggregate, entity, value object, ubiquitous language |
Hexagonal: ports and adapters
Hexagonal architecture makes the boundary explicit and symmetric. The application core defines ports, which are interfaces for what it needs (a repository, a notifier) and what drives it (a use-case interface). Adapters implement those ports: a REST controller and a CLI command are driving adapters, a PostgreSQL repository and an email client are driven adapters. There is no "outer layer", just the core and the things plugged into it.
Clean Architecture: concentric circles
Clean Architecture organizes the same idea into rings: entities at the centre (enterprise rules), use cases around them (application rules), interface adapters converting data for the outside, and frameworks and drivers at the edge. Source-code dependencies only ever point inward. In practice it is hexagonal architecture with a layering vocabulary and explicit names for the roles.
Onion: the same, renamed
Onion architecture predates Clean Architecture and is close enough that the difference is mostly historical. Domain model at the centre, application services around it, infrastructure on the outside, dependencies inward. If you understand Clean Architecture you understand onion; the terms are used almost interchangeably now.
DDD is not an architecture
Domain-Driven Design is about modelling. Strategic DDD identifies bounded contexts (the parts of the business with their own model and language) and how they relate. Tactical DDD gives you building blocks for the model inside a context: entities, value objects, aggregates, domain events, repositories. None of that says where the code sits or which way dependencies point. You apply DDD to decide what the domain layer contains, and hexagonal or Clean Architecture to decide how it is isolated. They are complementary, not alternatives.
In practice with PHP and Laravel
The concrete shape is the same under all three names: a framework-free domain (entities, value objects, use case or service classes), interfaces at the boundary, and Laravel-specific implementations (Eloquent repositories, controllers, jobs) wired in through the container. DDD, if you use it, shapes what goes in the domain layer and how you split it into contexts. The folder names differ between teams; the dependency direction does not.
// Domain: no framework imports
final class CancelSubscription
{
public function __construct(private SubscriptionRepository $subscriptions) {}
public function handle(SubscriptionId $id): void
{
$subscription = $this->subscriptions->get($id);
$subscription->cancel(); // aggregate enforces its own rules
$this->subscriptions->save($subscription);
}
}
// Infrastructure: implements the domain's interface with Eloquent
final class EloquentSubscriptionRepository implements SubscriptionRepository
{
public function get(SubscriptionId $id): Subscription { /* ... */ }
public function save(Subscription $subscription): void { /* ... */ }
}Which one do you choose?
You are not really choosing between hexagonal, Clean and onion; you are choosing to apply the dependency rule and picking the vocabulary your team will use consistently. Pick DDD as well when the domain is complex enough that modelling it deliberately pays off; skip the tactical patterns for a simple CRUD app where they add ceremony without benefit. The failure mode is applying the folder structure without the rule, which gives you the ceremony and none of the isolation.
FAQ
- Clean Architecture or hexagonal?
- They are the same core idea: dependencies point inward, the domain is isolated behind interfaces, external concerns plug in at the edges. Clean Architecture adds a layering vocabulary and named roles; hexagonal frames it as symmetric ports and adapters. Pick the vocabulary your team will use consistently; the structure is the same.
- Is DDD an architecture?
- No. Domain-Driven Design is a way to model the business (bounded contexts, aggregates, value objects, ubiquitous language) and organize teams around it. It says nothing about where code sits or which way dependencies point. You combine DDD with hexagonal or Clean Architecture, not instead of them.
- What is the difference between onion and Clean Architecture?
- Very little. Onion architecture came first and describes concentric layers with the domain at the centre and dependencies pointing inward. Clean Architecture consolidated onion and hexagonal into one diagram with named roles. The terms are used almost interchangeably today.
- Should I apply these patterns on every project?
- No. The dependency rule earns its keep when the domain logic is non-trivial and the application will live for years. For a small CRUD app or a short-lived tool, a framework-shaped structure is simpler and fine. Applying the folders without the rule is the worst of both.
- Can I combine DDD and Clean Architecture?
- Yes, and it is the common pairing. DDD decides what the domain layer contains and how you split the system into bounded contexts; Clean or hexagonal architecture decides how that domain layer is isolated from frameworks and infrastructure. They operate at different levels and fit together.
Hexagonal, Clean and onion architecture are three names for one rule: keep the domain independent and point every dependency toward it. DDD is a separate discipline for modelling that domain. Learn the rule, pick a vocabulary, add DDD when the domain warrants it, and do not let the folder structure become the goal.
Need help with this topic? Full Stack Development
Discover this service →