5 Hexagonal Architecture: Protecting the Core: The Power of Ports and Adapters
This chapter explains why protecting business logic from databases, user interfaces, and other external tools leads to cleaner, more testable software. It builds on dependency inversion by showing that the real goal is not just organizing code into layers, but shielding the application’s core so it can be exercised in isolation. The central idea is to stop thinking of the database as the foundation of the system and instead treat it as one of many replaceable details that connect to the core.
The pattern is described through the ideas of an inside, ports, and adapters. The inside contains the domain and orchestration logic, while ports define the contracts the core uses to communicate. Adapters live outside the core and translate between the core’s language and the messy realities of SQL, HTTP, consoles, or message queues. This inversion of dependencies makes the core independent, helps enforce separation of concerns, and allows new interfaces or infrastructure choices to be added without changing the business rules.
The chapter also shows how to apply the pattern in practice through examples, diagrams, and a small alerting system that can swap SMS, console, or Kafka implementations behind the same port. It highlights common mistakes such as leaking database types into the core, putting business rules in adapters, or designing ports around tables instead of use cases. Finally, it emphasizes trade-offs: hexagonal architecture improves maintainability and testability, especially for long-lived or complex systems, but it adds code, mapping, and conceptual overhead that may not be worth it for simple CRUD applications.
Layered Architecture can act like an anchor pulling everything down to the Database, while Hexagonal Architecture frees you of this concern.
In the Leaky System, database changes "bleed" through the layers, breaking the UI and business logic. In the Sovereign System, the Application Core is protected by Ports and Adapters, ensuring that external changes to the database or UI never touch your core business rules.
Visualizing the “Clean Room” being built with Hexagonal Architecture
Display showing how Ports interact with the Domain. Ports can share interfaces or be distinct; it all depends on cohesion (e.g., one IOrderPort vs. separate Ports).
Adapters translate the messy language of the outside world (JSON, SQL) into the clean language of the Core, and back again.
The Data goes out, but the Dependency points in. This is the Inversion.
The Laptop doesn’t care what device is plugged in as long as it fits in the Port!
A Medieval Castle is a perfect visual to picture how Hexagonal Architecture works in principle!
The Extensible Hexagon. Because the Application Core only communicates through defined Ports, you can easily plug in new "Future Adapters" (like a Mobile App or Admin CLI) without modifying a single line of your existing business logic.
On the Driven Side, the Domain Logic never talks to the database directly; it simply calls a Secondary Port (Interface). The actual database or email server is hidden inside a Secondary Adapter that implements the interface, allowing you to swap out your infrastructure without changing a single line of business logic.
Plugging in a different DB type is a breeze!
Archie (you!) remains safe in the Core from the blast if something happens to the API!
Cockburn wanted to make sure there was enough room implied thru the diagrams.
Look for the leaks to replace with Ports and Adapters!
Recap
- Hexagonal Architecture (also called Ports and Adapters) is a pattern designed to protect your most valuable asset, your Core Business Logic, from the messy, changing outside world.
- It flips the mental model from a vertical "stack" to a concentric "Inside vs. Outside" model.
- The Core (Inside) contains purely business logic and has zero dependencies on the outside world (no DB, no UI, no frameworks).
- Ports are the "airlocks" or interfaces defined by the Core. They specify what the Core needs or can do, without explaining how.
- Adapters are the translators that live on the Outside. They connect specific technologies (like a SQL database or a React app) to the Ports.
- The Golden Rule: All dependencies point INWARD. The Outside knows about the Inside, but the Inside knows nothing about the Outside.
- This architecture grants you the superpower of Testability. You can test your logic in isolation by plugging in "Fake" adapters, allowing for fast, reliable tests that run anywhere.
- Alistair Cockburn created the pattern to solve the problem of entanglement, allowing an application to be driven equally by a user, a program, or an automated test script.
FAQ
What is the main goal of Hexagonal Architecture?
Its main goal is to protect the core business logic from external concerns like databases, web frameworks, and user interfaces. The core should depend on nothing outside itself, which improves testability, maintainability, and flexibility.
What do “Inside,” “Ports,” and “Adapters” mean in this pattern?
Inside is the core business logic. Ports are interfaces that define how the core communicates with the outside world. Adapters are the concrete implementations that translate between external technologies and the core’s language.
Why is Hexagonal Architecture also called “Ports and Adapters”?
Because the pattern is fundamentally about using ports as contracts and adapters as the translation layer between the core and external systems. The hexagon shape is just a visual metaphor; the real idea is the port-and-adapter boundary.
What is the “Database First” trap?
It is the habit of designing software around database tables and schema instead of business behavior. This causes domain objects to mirror the database, which makes the core tightly coupled to storage technology.
Why does a layered architecture sometimes behave like “database gravity”?
Because dependencies tend to flow downward toward the database, making the database the hidden boss of the application. This can pull business rules into repositories or SQL queries and make the system harder to test and change.
What is the difference between a primary port and a secondary port?
A primary port defines how the outside world can drive or use the application, such as placing an order. A secondary port defines what the application needs from outside services, such as saving data or sending notifications.
What does a primary adapter do?
A primary adapter receives input from the outside world, such as an HTTP request or CLI command, translates it into the core’s language, and calls a primary port. Examples include controllers and command-line handlers.
What does a secondary adapter do?
A secondary adapter implements a secondary port and talks to external infrastructure such as databases, email services, or message brokers. It translates the core’s request into technology-specific operations.
What is the Composition Root?
The Composition Root is the place where the application is wired together, usually at the entry point like Program.cs or Main. It creates adapters and injects them into the core, keeping object creation out of the business logic.
When should you choose Hexagonal Architecture, and what is the tradeoff?
Choose it when you have complex business rules, multiple ways to interact with the app, or strong testability needs. The tradeoff is added complexity: more interfaces, mappers, and files, which can be overkill for simple CRUD or prototype apps.
Grokking Software Architecture ebook for free