Hexagonal Architecture
Updated June 8, 2026The Video Game Console Analogy
Think about a video game console, like a PlayStation or an Xbox.
The core of the console is its processor and the game engine. This is where all the rules of the game live. But to interact with it, you need inputs and outputs. You can plug in a standard controller, a racing wheel, or a VR headset. For output, you can plug it into an old 1080p TV, a 4K monitor, or a surround sound system.
The console itself doesn't care what controller you use, as long as the controller sends the right signals. It doesn't care what TV you use, as long as it accepts an HDMI cable.
This is exactly what Hexagonal Architecture (also known as Ports and Adapters) is all about.
Primary adapters (REST, CLI) call the domain through inbound ports. The domain calls outbound ports, which secondary adapters (PostgreSQL, Stripe) implement. The domain never imports infrastructure code.
Core Concepts
In traditional layered architecture, your business logic often gets tangled up with your database code or your UI/API code. If you want to swap out your MySQL database for MongoDB, or change your REST API to GraphQL, you have to rewrite a massive chunk of your application.
Hexagonal Architecture prevents this by isolating your core business logic in the center.
1. The Domain (The Console)
The absolute center of your application. This contains your core business rules and entities. It knows nothing about databases, web servers, or external APIs. It is pure code (like plain TypeScript classes or functions).
2. Ports (The Plugs)
Ports are interfaces defined by your Domain. They are the "rules of engagement."
- Inbound Ports (Primary): How the outside world talks to your domain (e.g., an interface for
CreateUserUseCase). - Outbound Ports (Secondary): How your domain talks to the outside world (e.g., an interface for
UserRepositorywith asave()method).
3. Adapters (The Controllers & TVs)
Adapters are the actual implementations that plug into your ports.
- Primary Adapters: Drive your application. A REST Controller, a GraphQL resolver, or a CLI script. They translate external requests and call the Inbound Ports.
- Secondary Adapters: Are driven by your application. A PostgreSQL repository, an AWS S3 file uploader, or a Twilio SMS sender. They implement the Outbound Ports.
Real-World Example: E-Commerce Payment Swap
Imagine you are building a checkout system. Your business rule is simple: "To complete an order, the user's payment must be captured."
The Old Way: Your checkout function directly imports the Stripe SDK and calls stripe.charges.create(). Now your core business logic is tightly coupled to Stripe. If Stripe goes down, or you want to switch to PayPal, you have to rewrite your checkout logic.
The Hexagonal Way:
- You create an Outbound Port: an interface called
PaymentGatewaywith a methodcharge(amount). - Your core domain logic uses this
PaymentGatewayinterface. It doesn't know what Stripe or PayPal is. - You create a
StripeAdapterthat implements thePaymentGatewayinterface. - Later, your company decides to switch to Adyen. You just write an
AdyenAdapter. You plug it in, and your core business logic doesn't change by a single line of code.
Why is it called a Hexagon?
The shape isn't mathematically significant. The creator, Alistair Cockburn, chose a hexagon simply because it has multiple sides, illustrating that an application can have many different inputs and outputs (web, CLI, database, message queues), moving away from the traditional "top-to-bottom" layered view.
Summary
Hexagonal Architecture (Ports and Adapters) protects your core business logic from the outside world. By forcing the domain to interact only through interfaces (Ports) and pushing all external technologies to the edges (Adapters), your application becomes easy to test, maintain, and adapt to changing technologies over time.
Saved on this device only
Sign in to sync progress across devices