Hexagonal Architecture

Method

A design approach that puts business rules at the center and pushes outside technology — the database, the payment provider — out to the edges as replaceable parts.

Why it exists

The longest-lived thing in a program is its business rules: annual billing takes two months off, a team over ten seats moves up a plan. The fastest-changing things are the technologies wrapped around those rules. Payment providers get swapped, databases get migrated, a web app grows a mobile client.

Written without care, the two fuse into one mass. The discount calculation happens in the same place that picks apart the payment provider's response, and the plan decision sits wedged between the statements that pull values out of the database.

Theo at Pagedeck lived that. Changing a single annual discount rate took two days. The edit itself took ten minutes, but confirming it worked meant spinning up a database on his machine and wiring in a sandbox account from the payment provider, and the account took a day to issue. Multiplication and subtraction were all the discount amounted to, and checking it required two services outside the company, neither of which had anything to do with the arithmetic.

The approach Alistair Cockburn described in 2005 inverts the order. Business rules go on the inside, and outside technology becomes a part that plugs into a contract the inside defines. That's what its original name, ports and adapters, refers to: the inside decides the shape of the socket and the outside comes to fit it.

How to run it

Six steps. You can start this way on a new system, or move tangled code toward it over time.

  1. Separate out the business rules. The code should never once name a database or a payment provider. That mass is usually called the core.
  2. List every place the core has to touch the outside world: where data is stored and retrieved, where payment gets handed off, where mail goes out, where requests from the screen arrive.
  3. Define a port at each of those places. A port states, in the language of the business, what the core needs from the outside. "Authorize a payment" is a port; "call the provider's authorization endpoint" is not. The moment a technology's name enters the contract, that technology can no longer be swapped.
  4. Split the ports by direction. Ports where the outside calls in are driving ports, and screens and APIs — the agreed doorways through which programs exchange requests — plug in there. Ports where the core calls out are driven ports, and that's where the database and the payment provider plug in.
  5. Build an adapter for each port. The adapter is the part that implements the contract with a real technology. One port can carry several adapters: the storage port might have a real database adapter alongside a test adapter that keeps everything in memory.
  6. Fix the direction of dependency. Adapters may know about the core; the core must not know about any adapter. So put the core in its own module and have the build refuse to let outside libraries in.

When it fits and when it doesn't

It pays off in products with thick, long-lived rules — pricing, inventory allocation, insurance premiums, where the company's arithmetic makes up a large share of the code and lasts for years. It pays off equally when outside technology is expected to change: replacing a payment provider, switching mail vendors, adding a mobile client to a web product.

The gain that gets felt first is testing speed. With a core that knows nothing about the outside, unit tests — the ones that isolate a single function or module — run without a database. A suite that took three minutes and now takes three seconds gets run ten times as often in a day, and a rate change that used to wait a day for a sandbox account gets confirmed in the same sitting.

The limits are just as clear. On a product with thin rules it's pure overhead. When most screens store what they receive and display it back, the ports and adapters end up outnumbering the rules they surround.

The expectation of freely swapping technology is only half right. Providers doing roughly the same job swap out with a new adapter, but moving from a relational database to a document store changes how data is handled at all, and the shape of the port changes with it.

How it sounds at work

"Handle that in the adapter. The provider's response format shouldn't reach the core."

Blocking one technology's particulars from leaking inward.

"Switching providers is a new adapter, so two weeks. The discount rules don't get touched."

Answering the scope of a technology swap as a schedule.

"This test runs without a database. I plugged a fake adapter into the storage port."

Possible only because the core doesn't know what's behind the port.

When Pagedeck decided to move payment providers, Grace asked how long it would take. The structure is why Theo could answer two weeks. The only thing to replace was the adapter plugged into the payment port, and the annual discount and plan-upgrade rules sat in the core without knowing the provider's name.

One exception surfaced in the same meeting. Refunds had been handled differently, and the format of the provider's notification had made it all the way into the core. That part took more than an adapter swap — the rule code had to change with it, and four of the two weeks went there. The rest of the swap landed on the original estimate.

What people get wrong

People read meaning into the hexagon. Given the name, it's natural to look for six of something. There isn't any. Drawing a shape with several sides was a way to show that many faces touch the outside, rather than the top and bottom a rectangle offers; the number of attached faces might be four or nine. The shape is a picture, not a count. The name to remember is ports and adapters.

The other frequent mistake is filing it as a choice about deployment units. Seen in a list next to monolith and microservices, it looks like one of three options. But those two answer how many pieces get shipped to a server at once, and this one answers how a single piece is arranged inside. Different levels, so they combine: writing one monolith this way makes sense, and so does writing five microservices each this way. Treat it as a three-way choice and the deployment decision and the internal structure decision get tangled in one meeting, with neither one settled.

Easily confused with

TermWhat it dividesHow it differs
Layered architectureStacks presentation, business, and data into three levelsCalls run one direction, from the screen down to the database, which leaves the business layer resting on the data layer. Hexagonal reverses that direction and treats the database as a part outside the business rules, so replacing it leaves the business code alone. The stack is about who calls whom; the hexagon is about who is allowed to know whom

Where to go next

  • Software architecture

    see which other decisions this one sits beside, and how it separates from the deployment question

  • Monolith

    the deployment unit this structure most often rides on, a pairing that's common in practice

Last updated 2026-09-16