Hexagonal Architecture (Ports and Adapters)
Hexagonal architecture isolates business logic. After implementing it in production, here’s how to structure applications effectively.
What is Hexagonal Architecture?
Hexagonal architecture:
- Ports - Interfaces
- Adapters - Implementations
- Domain - Business logic
- Isolation - Technology-agnostic
Structure
┌─────────────┐
│ Adapters │
│ (Driving) │
└──────┬──────┘
│
┌──────▼──────┐
│ Ports │
│ (Driving) │
└──────┬──────┘
│
┌──────▼──────┐
│ Domain │
│ Logic │
└──────┬──────┘
│
┌──────▼──────┐
│ Ports │
│ (Driven) │
└──────┬──────┘
│
┌──────▼──────┐
│ Adapters │
│ (Driven) │
└─────────────┘
Implementation
Domain (Core)
// Domain entity
class Order {
constructor(
public id: string,
public items: OrderItem[],
public total: number
) {}
calculateTotal() {
return this.items.reduce((sum, item) => sum + item.price, 0);
}
}
// Port (interface)
interface OrderRepository {
save(order: Order): Promise<void>;
findById(id: string): Promise<Order | null>;
}
Adapters
// Driven adapter (database)
class PostgreSQLOrderRepository implements OrderRepository {
async save(order: Order) {
await db.orders.insert(order);
}
async findById(id: string) {
return await db.orders.findOne({ id });
}
}
// Driving adapter (HTTP)
class OrderController {
constructor(private orderService: OrderService) {}
async createOrder(req: Request, res: Response) {
const order = await this.orderService.createOrder(req.body);
res.json(order);
}
}
Best Practices
- Isolate domain - No dependencies
- Define ports - Clear interfaces
- Implement adapters - Technology-specific
- Test domain - Unit tests
- Mock adapters - Integration tests
- Dependency injection - Loose coupling
- Keep it simple - Don’t over-engineer
- Document ports - Clear contracts
Conclusion
Hexagonal architecture enables:
- Testable code
- Technology independence
- Clear boundaries
- Maintainable systems
Start with domain, then add ports and adapters. The architecture shown here isolates business logic effectively.
Hexagonal architecture from August 2022, covering ports, adapters, and domain isolation.