What is hexagonal architecture (ports and adapters)?
A way to structure software so that the application core talks to databases, user interfaces and outside services only through ports, with swappable adapters.
Hexagonal architecture, also called ports and adapters, is a way of organizing an application so that its core, meaning the business rules, never talks directly to databases, user interfaces or outside services. It communicates only through ports, interfaces the application itself defines and names after their purpose, such as "for getting tax rates". Each technology plugged into a port gets an adapter, the code that translates between the port and that specific system. Alistair Cockburn proposed it in a 2005 technical report with a clear goal: let the application be driven equally by people, other programs, automated tests or scheduled batch jobs, and let it be built and tested without the databases and devices it will eventually run against. The hexagon has nothing to do with the number six: it leaves room to draw the ports, which in 2005 Cockburn preferred to keep to two, three or four.
See also: CQRS · Splitting the model that writes data from the one that reads it, instead of using a single model for both jobs.
What it buys and what it costs
The first benefit is testing: an adapter can be a fake in-memory database, so automated tests check the business logic without the real one. The second is replaceability: among the benefits in the slides from a 2025 talk, Cockburn lists the ability to change the connected systems at startup or over the years without touching the core. That is a practical defense against vendor lock-in in the code: the dependency on the vendor stays inside its adapter instead of spreading through the codebase. The third is integration: every function exposed on a port can also be used by another program.
The same deck has a "Costs" page. Every outside system the application calls needs a place to plug in, and one component must assemble the right pieces at startup; statically typed languages such as Java also need declared interfaces and folders for the ports. The 2024 AWS guide to cloud design patterns adds that adapter code is justified only when there are several data sources and destinations, or when they will change over time; otherwise it is one more layer to maintain, and either way it may add latency. This is not a deployment decision: it concerns the internals of a single program, and applies equally to a monolith or a microservice.
An enterprise example
A distributor sells online, and its order-management system calls the payment provider's API in dozens of places: confirmations, returns, refunds. If a rival provider offers lower fees, switching touches the whole codebase and calls for a full retest. With hexagonal architecture the core knows only a port "for collecting a payment" and the provider lives in an adapter. Switching means writing a new one and running both on the same port for a while, because refunds on past payments still go through the old provider. The same holds for the ERP: behind a port "for recording an invoice", the old and new systems can run side by side during a gradual replacement, an approach known as the strangler fig pattern. The port does not make the switch free: if the new provider handles refunds differently, the port has to be redesigned too.
Why it matters for decision makers
It is an investment paid up front, and it pays off only if something actually changes (a supplier, a database, an extra channel) or if reliable automated tests are needed. In a small application that only creates, reads and updates records it is almost always wasted effort. Jeffrey Palermo says as much about the related onion architecture he described in 2008: not appropriate for small websites, appropriate for long-lived business applications. AWS's own guides disagree with each other: one from 2022 recommends it for every enterprise project regardless of complexity, within each bounded context. Before approving it I ask for a list, not a yes: which outside systems are expected to be replaced, and whether isolating them today costs less than rewriting around them later.
Related terms
- CQRS · Splitting the model that writes data from the one that reads it, instead of using a single model for both jobs.
- Bounded context · An explicit boundary within which a business term has one coherent meaning, instead of one forced global data model.
- Strangler fig pattern · Replacing a legacy system gradually, routing traffic to the new one until the old system is no longer needed.
- Microservices vs monolith · Two opposite ways to structure an application: one deployable unit versus independent services. The modular monolith is often the right middle ground.
- Vendor lock-in · The technical and contractual cost of leaving a vendor: data, logic, skills. Measured before signing, not after.
If it reminds you of a system nobody dares touch anymore, that is what I put back in order.
SEE SOFTWARE RESCUE