Hexagonal Architecture
Core Idea
Examples and diagrams in this page follow the shared Hypothetical Scenario.
Many systems start from framework and database setup. Business rules then spread across controllers, mappers, and transport handlers. Testing turns slow, and technology shifts become expensive.
Hexagonal Architecture addresses this drift. Core behavior stays in the center. Ports define required interactions. Adapters connect concrete technologies to those ports.
Historical Context
Alistair Cockburn introduced the pattern to solve one recurring failure mode. Applications were tied to user interface and database decisions from the start. Teams could not run core behavior without full infrastructure setup.
The hexagon shape is a teaching aid. It shows multiple symmetric entry and exit points. It avoids the old top and bottom layer mindset.
Sources: Cockburn (2005)
The Problem It Solves
Traditional layering often mixes policy and plumbing. Request mapping, validation, business rules, and persistence calls end in the same classes. Core behavior then depends on delivery and storage details.
This creates recurring risk:
- Slow tests tied to infrastructure bootstrapping
- High rewrite cost after framework migration
- Duplicate business rules across entry points
- Coupling between domain logic and transport formats
Main Concept
Hexagonal Architecture separates three concerns. The center holds application and domain behavior. Ports describe interaction contracts around that center. Adapters implement those contracts at the system edge.
Ports can be driving or driven. Driving ports are called by inbound adapters such as HTTP or CLI handlers. Driven ports are called by core logic to reach external systems.
Hexagonal structure view. Ports define stable contracts around core behavior.
How It Works
A request enters through an inbound adapter. The adapter converts transport data into an application command. The command reaches a driving port. Core logic runs business rules and orchestrates use case steps.
When external access is needed, core logic calls a driven port. An outbound adapter implements that port for concrete tooling. Core behavior stays isolated from database and protocol details.
Request flow view. Adapters translate data at boundaries. Core logic stays transport agnostic.
Designing a System with Hexagonal Architecture
Architects can apply the model through a clear sequence.
- Define bounded contexts and major use cases.
- Model domain behavior and invariants.
- Define driving ports for each use case.
- Define driven ports for persistence, messaging, and external services.
- Implement inbound adapters for required channels such as HTTP, CLI, jobs, and events.
- Implement outbound adapters per infrastructure target.
- Add contract tests for ports and integration tests for adapters.
- Add architecture tests that block adapter imports inside core packages.
This sequence keeps design intent visible. Core use cases remain runnable without full infrastructure.
Challenges and Shortcomings
Hexagonal Architecture gives strong testability and decoupling. It carries tradeoffs that teams should plan for.
Common friction points:
- Interface and adapter count can grow quickly
- Mapping code can feel repetitive in small projects
- Weak port naming creates vague contracts
- Teams may place framework types inside core packages
- Cross cut concerns can leak if boundaries lack review discipline
Small short lived products may not need full hexagonal separation. Long lived systems with frequent integration change often gain clear value.
Link to Existing Handbook Concepts
| Concept | Why? |
|---|---|
| Abstraction and Boundaries | This model aligns with Abstraction and Boundaries. Ports and adapters are explicit boundary contracts. |
| Modularity and Composition | This model aligns with Modularity and Composition. Each adapter composes one focused responsibility. |
| Simplicity First | This model aligns with Simplicity First. Boundary clarity lowers change blast radius. |
| Onion Architecture | This model aligns with Onion Architecture. Both models protect core behavior through inward dependency direction. |
Hexagonal Architecture and Microservices
Hexagonal Architecture and microservices target different scopes. Hexagonal design structures one service internally. Microservices define system level service boundaries.
A practical system design uses both ideas together. Each microservice can adopt one internal hexagon. Service APIs and events become inbound and outbound adapter channels. Domain behavior in each service remains independent from transport detail.
This composition helps in distributed systems:
- Faster service testing through core isolation
- Lower migration cost for framework and storage changes
- Clearer responsibility boundaries per service
Microservice composition view. Each service owns a hexagon with local ports and adapters.
Practical Notes
Hexagonal Architecture is a design discipline, not a library feature. Its value depends on boundary quality and naming quality. Teams should review contracts as carefully as business rules.
Written by: Pedro Guzmán
See References for complete APA-style bibliographic entries used on this page.