The Code Codex
Theme
← Notes / Architecture

note · text31 Jan 2025 · 2 min

Hexagonal architecture

There are two kinds of complexity in a system:

  • Business complexity: the rules that give the software its value.
  • Technical complexity: frameworks, databases, queues, protocols.

Hexagonal architecture, proposed by Alistair Cockburn in 2005 under the name Ports and Adapters, separates the two. Frameworks and dependencies can then be replaced or upgraded without interfering with the business rules.

Domain (core)

REST adapter

Input port

CreateOrder

CLI adapter

Test

Business rules

Output port

OrderRepository

Postgres adapter

In-memory adapter

Domain (core)

REST adapter

Input port

CreateOrder

CLI adapter

Test

Business rules

Output port

OrderRepository

Postgres adapter

In-memory adapter

  • Domain: the business rules. It imports nothing from frameworks, databases or HTTP.
  • Ports: interfaces defined by the domain. Input ports say what the system does (use cases); output ports say what it needs from the world (save an order, send an email).
  • Adapters: the technical implementations that plug into the ports: a REST controller, a Postgres repository, an email client.

The rule that holds it all together: dependencies point inward. The domain doesn’t know the adapters; the adapters know the domain.

// output port, defined by the domain
type OrderRepository interface {
Save(order Order) error
}
// use case: only knows the port
func CreateOrder(repo OrderRepository, items []Item) (Order, error) {
order := NewOrder(items) // business rules
return order, repo.Save(order)
}

In production, repo is the Postgres adapter; in tests, an in-memory version, without starting any database.

Why it pays off
  • Sustainable growth: the software stays easy to change over time.
  • Software has to pay for itself over time, and swapping a technology shouldn’t require rewriting the business.
  • The software should be designed by you, not by the framework.
  • The pieces need to fit together and, eventually, be replaced.

The cost is more structure (interfaces and mappings) than a simple CRUD needs. It is worth it when there are real business rules.

See also: Software architecture fundamentals.