Clean Architecture
also called Onion Architecture
Concentric layers with dependencies pointing inward, so business rules know nothing about frameworks, databases or delivery mechanisms.
Definition
Concentric rings: entities and use cases at the centre, interface adapters outside them, frameworks and drivers at the edge. The dependency rule: source code dependencies point only inward. The domain knows nothing about the database, the HTTP framework, or the message broker.
What it actually buys
- The domain is testable without infrastructure. Unit tests run in milliseconds with no database, which changes how often people run them and therefore how much they help.
- Infrastructure is replaceable. Swapping a database or a framework touches the outer ring.
- Business rules are readable without knowing the framework, which matters for onboarding and for the conversation with domain experts.
- Framework churn is contained. Web frameworks change every few years; business rules do not.
What it costs
- Mapping. Domain objects, persistence models and API models are separate types with translation between them. Real work, and it feels like ceremony until the day it saves you.
- Indirection. More files, more interfaces, more navigation to follow a request.
- Losing framework conveniences that assume direct coupling — some ORMs, some validation mechanisms, some scaffolding.
- A learning curve that produces inconsistent implementations if the team is not aligned.
When it is worth it
Rich domain logic with a long life. Insurance policies, financial instruments, healthcare scheduling, logistics rules. The domain complexity justifies protecting it, and the system will outlive its frameworks.
Not worth it for CRUD over a database, where the "domain" is a table and the mapping ceremony exceeds the logic being protected. A straightforward layered application is better, and pretending otherwise produces four types where one would do.
The most common failure
Anaemic domain plus full ceremony. All the mapping, all the interfaces, all the directory structure — and the entities are data bags while the logic sits in service classes. Every cost, none of the benefit. If the domain objects have no behaviour, clean architecture is protecting nothing.
Failure scenarios
- Leaking framework types inward — an ORM entity or an HTTP request object in the domain, which silently inverts the dependency rule.
- Applied to a CRUD application, producing indirection with no protected complexity.
- Interfaces for everything, including things with one implementation and no plausible second.
- Inconsistent application across a codebase, so nobody knows which rules apply where.
Interview question
"When is clean architecture over-engineering, and what is the signal that you have its costs without its benefits?"