Based on the concentric-circle architecture model proposed by Jeffrey Palermo (2008), with the Domain at the center and dependency direction strictly pointing to the inner layers.
Workflow
Step 1: Applicability check — determine whether the project suits the onion architecture | Reference: SKILL.md When to Use
Step 2: Set up the directory skeleton — create the four-layer modules core/infrastructure/api/composition | Reference: references/04
Step 3: Write the Domain core — aggregate roots, value objects, Repository interfaces, domain events (zero framework dependencies) | Reference: references/01
Step 4: Write Application interfaces — application service interface contracts, pure orchestration without business logic | Reference: references/02
Step 5: Write Infrastructure implementations — implement the Domain layer's Repository/MQ/external clients | Reference: references/03
Step 6: Write API adapters — Controller, DTO, Assembler, global exception handling | Reference: references/04
Step 7: Configure DI assembly — centralized wiring in the composition module | Reference: references/05
Step 8: Write tests — Domain layer unit tests → Application Mock → Infra integration tests | Reference: references/06
Step 9: Gotchas check — verify item by item against common pitfalls | Reference: the pitfalls section of each references file
Step 10: Migration (if applicable) — gradual migration from three-tier to onion | Reference: references/07
When to Read (triggers)
| User question | Loading action |
|---|---|
| "Help me set up a project with the onion architecture" | Open SKILL.md + references/01-05 |
| "Where should the Repository interface go?" | Open references/01-domain-model |
| "How do you test the onion architecture?" | Open references/06-testing |
| "How do you migrate from three-tier to onion?" | Open references/07-migration-from-layered |
| "What's the difference between onion and hexagonal?" | Open references/08-comparison |
| "Does onion support CQRS?" | Open examples/example-04-cqrs-onion |
| "How do you design multiple entry points?" | Open examples/example-03-multi-entry |
| "How do you configure DI in Spring Boot?" | Open references/05-di-composition |
When to Use
| ✅ Applicable scenarios | ❌ Not applicable |
|---|---|
| Infrastructure changes frequently (DB/MQ/cache vendor replacement) | Simple CRUD projects (over-engineering) |
| Unit test coverage requirement > 80% | Prototypes/PoCs delivered in two weeks |
| Multi-entry systems (REST + CLI + MQ + gRPC) | Simple services with a single entry point + single database |
| The team has interface abstraction and DI design capabilities | The team is unfamiliar with dependency inversion |
| Complex business rules requiring strict isolation | Three-tier architecture is sufficient |
Boundary
| Area | Ownership |
|---|---|
| Three-tier→onion migration | ✅ This Skill (references/07-migration) |
| Onion vs Hexagonal vs Clean Comparison | ✅ This Skill (references/08-comparison) |
| Selection Decision | ❌ Use ddd-architecture-selector |
| Domain Modeling | ❌ Use ddd-domain-designer |
| Code Review | ❌ Use ddd-code-reviewer |
| COLA Project | ❌ Use ddd-architecture-cola |
Audience
This skill is designed for: Backend developers (implementing DDD architectures), Software architects (evaluating and selecting patterns), Tech leads (reviewing team implementations), and DDD beginners (learning domain-driven design fundamentals).
Core Principle: Concentric Circle Dependency Rule
All dependencies point toward the center (Domain); inner layers define interfaces, outer layers implement interfaces.
Infrastructure → API/Adapters → Application → Domain Core ★
所有依赖指向圆心,内层零框架依赖。
Jeffrey Palermo's Four Principles
- Application core is independent of infrastructure — The Domain layer does not import any framework/database classes
- Inner layers define interfaces, outer layers implement — e.g.
OrderRepositoryinterface in Domain, implementation in Infrastructure - Dependencies point toward the center — Infrastructure → Application → Domain, reverse direction not allowed
- Outer layers know inner layers, inner layers do not know outer layers — Domain knows nothing about Infrastructure
Rules
| # | Rule | Detection Method | Level |
|---|---|---|---|
| 1 | Domain layer has zero framework dependencies | Search for framework imports in the Domain package | P0 |
| 2 | Repository interfaces in Domain, implementations in Infra | Check interface/implementation locations | P0 |
| 3 | Application layer is pure orchestration, contains no business if/else | Code review | P0 |
| 4 | Value objects are immutable (final fields, no setters) | ValueObject class check | P1 |
| 5 | Cross-aggregate references via ID | Aggregate root field type check | P1 |
| 6 | DTOs are defined in the API layer and not leaked into Domain | Check DTO imports in Domain | P0 |
| 7 | Composition Root centrally manages DI | Check whether each layer has new dependency |
P1 |
See references/08-comparison.md for a detailed comparison of Onion vs Hexagonal vs Clean Architecture.
Directory Structure
{project}/
├── {project}-core/domain/ # 领域模型(零框架依赖)
├── {project}-core/application/ # 应用服务接口
├── {project}-infrastructure/ # Repository 实现、MQ、外部集成
├── {project}-api/ # Controller、DTO、Assembler
└── {project}-composition/ # DI 组装
Module Dependency Rules
| Module | Can Depend On | Cannot Depend On |
|---|---|---|
| core/domain | None (pure Java) | Spring/JPA/MyBatis |
| core/application | domain | infrastructure, api |
| infrastructure | core | api |
| api | core, infrastructure | — |
| composition | All modules | — |
Development Standards (see references for details)
| # | Standard | Violation Example |
|---|---|---|
| 1 | Domain has zero framework dependencies | import org.springframework.stereotype.Service |
| 2 | Repository interfaces in Domain | Both interface and implementation in Infra |
| 3 | Application only orchestrates, does not implement | AppService contains business decisions |
| 4 | Transaction boundary in Application | Controller or Repository starts transactions |
| 5 | Cross-aggregate via domain events | Aggregate A directly references Aggregate B |
| 6 | Value objects are immutable | ValueObject has setters |
| 7 | Rich domain model entities | Entities only have getters/setters |
| 8 | DTOs are defined in the API layer | DTO imports in Domain |
| 9 | Composition Root is the outermost layer | Each layer does its own new dependency |
| 10 | Strict layering | API directly calls Infrastructure |
Gotchas — (see the pitfalls section of each reference for details)
15 core pitfalls: Domain layer framework leakage / Repository interface location / Application too thick / over-abstraction / scattered Composition Root / mutable value objects / aggregate root too large / direct cross-aggregate references / Controller containing business logic / DTO leakage / PO annotations / missing events / transactions spanning aggregates / Infra intruding into tests
FAQ — (see references/08-comparison.md and the references for each layer)
Covers: onion vs hexagonal, Domain framework restrictions, value objects vs entities, Repository interface location, aggregate size, migration strategy, CQRS compatibility, test levels, microservice adaptation, events across services, etc.
Keywords
onion architecture, 洋葱架构, Jeffrey Palermo, domain-centric architecture,
layered isolation, dependency inversion, 依赖倒置, concentric layers,
core/domain, application interfaces, infrastructure implementation,
API adapters, composition root, DI assembly, domain model,
repository pattern, aggregate root, value object, domain service,
DDD layered, clean architecture comparison, hexagonal comparison
References
| File | Purpose |
|---|---|
| references/01-domain-model.md | Domain layer design in detail: aggregate roots, value objects, domain services |
| references/02-application-interfaces.md | Application layer interface design: service orchestration and transaction boundaries |
| references/03-infrastructure-implementation.md | Infrastructure layer implementation: Repository, MQ, external integration |
| references/04-api-adapters.md | API adapter layer: Controller, DTO, Assembler |
| references/05-di-composition.md | DI assembly: Composition Root configuration |
| references/06-testing.md | Testing strategy: unit tests, integration tests, contract tests |
| references/07-migration-from-layered.md | Complete path for migrating from a three-layer architecture to an onion architecture |
| references/08-comparison.md | Detailed comparison of onion vs hexagonal vs clean architecture |
Examples
Business scenario examples
| Example | Description |
|---|---|
| examples/example-01-order-payment.md | Complete order payment example (including Domain/Application/Infra/API) |
| examples/example-02-product-catalog.md | Product catalog management example (including multi-aggregate collaboration) |
| examples/example-03-multi-entry.md | Multi-entry system example (three adapters: REST + MQ + CLI) |
| examples/example-04-cqrs-onion.md | CQRS + onion fusion example (Command/Query separation) |
| examples/example-05-user-registration.md | User registration + email verification example |
Project scale examples
| Example | Description |
|---|---|
| examples/06-monolith-simple.md | Simple monolith: single-module project, one bounded context |
| examples/07-monolith-complex.md | Complex monolith: single module with multiple bounded contexts, internally isolated |
| examples/08-monolith-multi-module.md | Multi-module monolith: Maven multi-module enforcing layering |
| examples/09-microservice-simple.md | Simple microservice: single service, single context onion |
| examples/10-microservice-complex.md | Complex microservice: single service with multiple contexts internally isolated |
| examples/11-microservice-multi-module.md | Multi-module microservice: single service Maven multi-module onion |
| examples/12-microservice-complex-multi.md | Complex multi-module microservice: multi-context Maven multi-module |
Primary Sources: Onion Architecture Part 1-4 — Jeffrey Palermo (2008) · DDD Blue Book — Eric Evans (2003) · Implementing DDD — Vaughn Vernon (2013)
Implementation: Microsoft DDD Microservice · Testcontainers
Output
Responses always include: applicability assessment → directory structure → code template for each layer → DI assembly → test skeleton → Gotchas compliance check. For details, refer to the references/ and examples/ files.
Skill journey
📍 Current: Onion architecture implementation
← Previous:hand off to the ddd-architecture-selector skill(Install: npx skills add full-stack-skills/ddd-skills --skill ddd-architecture-selector)
→ Next:hand off to the ddd-domain-designer skill(Install: npx skills add full-stack-skills/ddd-skills --skill ddd-domain-designer)
🔗 Related:hand off to ddd-cqrs-architecture skill(Install: npx skills add full-stack-skills/ddd-skills --skill ddd-cqrs-architecture) | ddd-code-reviewer skill(Install: npx skills add full-stack-skills/ddd-skills --skill ddd-code-reviewer)
🏠 Home:hand off to ddd-architecture-awesome skill(Install: npx skills add full-stack-skills/ddd-skills --skill ddd-architecture-awesome)
Core mantra: inner layers define interfaces, outer layers implement interfaces, dependencies point toward the center.
Security & Safety
This skill is pure documentation. It contains no executable scripts, collects no user data, accesses no external services or networks.
Verification checklist
- Domain layer has no framework imports
- Repository interfaces are in the Domain layer
- Repository implementations are in the Infrastructure layer
- Application layer has no business if/else
- Value objects are immutable
- Cross-aggregate references are by ID
- DTOs are defined only in the API layer
- DI is centralized in the composition module
- Domain events have been published