Practice : Hexagonal (Ports & Adapters) Architecture
Purpose and Strategic Importance
Hexagonal Architecture (also known as Ports & Adapters) is a software design pattern that promotes separation of concerns by isolating the core business logic from external systems. This makes applications easier to test, adapt, and evolve by allowing changes at the edges without affecting the centre.
By applying this pattern, teams achieve better modularity, testability, and resilience - enabling sustainable growth, clean architecture, and a deep alignment between business rules and system design.
Description of the Practice
- The core domain logic (application or business rules) lives in the centre.
- Ports define interfaces through which the core communicates with the outside world.
- Adapters implement ports to connect to databases, APIs, UIs, queues, etc.
- Inbound adapters bring input into the core (e.g. controllers, CLI).
- Outbound adapters allow the core to call external services (e.g. repositories, clients).
- Dependencies flow inward - outer layers depend on inner layers, never the reverse.
How to Practise It (Playbook)
1. Getting Started
- Identify business logic that is tightly coupled to frameworks or infrastructure.
- Extract the core logic into a standalone module with clear interfaces.
- Define ports as interfaces or contracts that express the inputs/outputs needed by the core.
- Create adapters to connect existing infrastructure to these ports.
2. Scaling and Maturing
- Apply the architecture consistently across services to support maintainability.
- Replace real adapters with test doubles for fast and reliable unit testing.
- Introduce dependency injection or inversion of control to manage wiring.
- Use DDD to shape your domain layer, aligning closely with business language.
- Keep adapters thin and focused on translation between formats or protocols.
3. Team Behaviours to Encourage
- Focus tests on the domain logic, not the integration details.
- Evolve the system by changing adapters, not the core, where possible.
- Review layering and interface ownership during design and code reviews.
- Ensure language and terminology in ports reflect business understanding.
4. Watch Out For…
- Overengineering in simple systems - use hexagonal only where it adds value.
- Leaky abstractions in ports that expose adapter details.
- Duplicated logic across adapters instead of encapsulating in the core.
- Drift between ports and actual implementation - ensure contracts stay valid.
5. Signals of Success
- Business logic is testable independently of infrastructure.
- Changes to frameworks, APIs, or databases require minimal core changes.
- Teams can onboard quickly by understanding the domain layer first.
- Codebases are modular, understandable, and aligned with business outcomes.
- Architecture supports experimentation, replacement, and long-term maintainability.