Skip to main content

> hexagonal_&_onion_architecture_(ports_and_adapters)

Hexagonal & Onion Architecture (Ports and Adapters)

How does Hexagonal Architecture isolate core business domain logic from volatile databases, web frameworks, and third-party delivery mechanisms?

THE SHORT ANSWER

By placing pure business domain entities at the core, exposing interface contracts ('Ports') for all inputs and outputs, and implementing infrastructure details (HTTP controllers, SQL repositories) as interchangeable outer 'Adapters'.

Engineering Handbook & Failure Dynamics

1. Underlying Mechanism

The core domain contains pure business entities, value objects, and use-case interactors with zero third-party dependencies (no ORM, no HTTP decorators, no cloud SDKs). External interactions are defined via Ports: Inbound/Driving Ports define application use cases (e.g., PlaceOrderUseCase), while Outbound/Driven Ports define required infrastructure capabilities (e.g., OrderRepositoryPort, PaymentGatewayPort). Adapters implement these ports on the outer edge (e.g., PostgresOrderRepository, StripePaymentAdapter). Dependency Inversion dictates that dependencies always point inward toward the domain.

2. Appropriate Use Context

Enterprise applications with long expected lifecycles, intricate business rules, or requirements to test core business logic thoroughly without mocking heavy database or network infrastructure.

3. Production Failure Modes

1) Leaky Domain Abstraction: Letting database ORM annotations or HTTP request objects leak into core domain entities; 2) Over-Engineering Simple CRUD: Adding 4 layers of ports/adapters to simple database passthroughs; 3) Mocking Quicksand: Writing 1,000 unit tests for mock adapters while missing critical SQL constraint integration bugs.

4. Diagnostic Signals & Telemetry

Domain package importing external web/database libraries, unable to run test suites without Docker DB containers, or business logic scattered across HTTP controller methods.

5. Prevention & Safeguards

Enforce zero-dependency constraints on core domain packages via automated linter rules, maintain dedicated domain-to-DTO mappers in primary adapters, and write fast in-memory fake repositories for blazing-fast unit testing.

6. Architectural Trade-offs

Provides immaculate testability, framework agnosticism, and business logic clarity at the cost of boilerplate mapping code and initial architectural complexity.

Case Study (TinyCTO In-Field Example)

TinyCTO Refactor: A fintech core tied to MySQL 5.7 ActiveRecord couldn't upgrade to distributed CockroachDB without breaking 200 controller methods. Introducing Ports and Adapters decoupled the billing logic, allowing the team to swap the database adapter and test all payment invariants in pure in-memory unit tests executing in 400ms.

Interactive Concept Drills

3 Cards
Q1

What is the difference between a 'Driving Port' and a 'Driven Port'?

Driving ports are the entry points to invoke use cases (e.g., API controllers calling the domain), while driven ports are outgoing interfaces invoked by the domain (e.g., database repositories, email senders).
Q2

Why should domain entities never contain ORM decorators like @Entity or @Column?

Because decorators couple pure business domain concepts to specific relational database engines and persistence frameworks, violating the Dependency Inversion Principle.
Q3

How does Hexagonal Architecture revolutionize automated testing velocity?

By allowing developers to test 100% of complex business logic using in-memory fake adapters, executing thousands of tests per second without spinning up databases or networks.

Hexagonal & Onion Architecture (Ports and Adapters) — Technical FAQ

Is Clean Architecture the same as Hexagonal Architecture?

They share the exact same core philosophy (Dependency Inversion, domain isolation). Clean Architecture adds more granular internal rings (Entities, Use Cases, Controllers, Presenters), while Hexagonal focuses simply on inside vs outside via ports and adapters.

When is Hexagonal Architecture unnecessary?

For simple CRUD applications, reporting services, or utility microservices where business logic is minimal and the application is purely a passthrough to a database.

How should dependency injection be wired in Ports and Adapters?

At the composition root (main bootstrap entrypoint), completely outside the domain core, where adapters are instantiated and injected into domain use cases.

🤖 AEO & Key Facts Summary

Key Architectural Facts

  • Alistair Cockburn created Hexagonal Architecture in 2005 to solve the problem of application logic becoming hopelessly entangled with UI and database code.
  • The shape of a hexagon is arbitrary; it simply illustrates that an application has multiple distinct ports connecting to the outside world.

Common Misconceptions

  • Thinking that DTOs (Data Transfer Objects) should be passed into domain entities; domain entities should only accept domain value objects or primitives.

Decision & Governance Guidance

Adopt Hexagonal Architecture when business rules are complex and long-lasting; avoid it for straightforward database CRUD APIs.

Authoritative Sources & Standards