Skip to content
IRC-CodingIRC-Coding
Hexagonal ArchitecturePorts and AdaptersDependency InversionClean ArchitectureSoftware Architecture

Hexagonal Architecture: Ports and Adapters Explained

Hexagonal Architecture (Ports and Adapters) guide: domain core, ports, adapters, dependency inversion, examples, exam questions.

S

schutzgeist

6 min read
Hexagonal Architecture: Ports and Adapters Explained

Hexagonal Architecture

This article explains Hexagonal Architecture (Ports and Adapters), including typical exam questions, key takeaways, and review tags.

What is Hexagonal Architecture?

Hexagonal Architecture (also called Ports and Adapters) is an architectural pattern that strictly separates the business core (domain and use cases) from external dependencies, such as:

  • UI (web, mobile, CLI)
  • Databases
  • Message brokers
  • third-party APIs

The core idea: the domain defines what it needs (ports/interfaces). The infrastructure provides interchangeable implementations (adapters).

The Building Blocks: Domain, Ports, Adapters

Domain Core

At the centre sits your business logic:

  • Entities and Value Objects
  • Use Cases and Application Services
  • Business rules

Ports

Ports are interfaces that establish the direction of dependencies:

  • Inbound Ports: what the application offers (use cases, commands)
  • Outbound Ports: what the application needs (repositories, payment providers, mail services, logging)

Adapters

Adapters connect ports to concrete technology:

  • Inbound Adapters: REST controllers, GraphQL resolvers, CLI commands, schedulers
  • Outbound Adapters: database repositories, HTTP clients, caches, message producers

Why Is This Helpful? (Benefits)

  • Testability: core logic can be tested without a database or HTTP calls (mocks/fakes on ports)
  • Interchangeability: swapping technology only affects adapters, not the core
  • Loose Coupling: fewer framework dependencies in domain code
  • Clear Responsibilities: well-defined system boundaries

Typical Drawbacks and Trade-offs

  • More abstraction (ports/adapters) means more artifacts
  • Higher initial effort (wiring, dependency injection, mapping)
  • Learning curve for teams accustomed to writing directly against frameworks

Mini Practical Example (Simplified)

Idea

A use case like “pay order” knows only ports. A Stripe adapter or database adapter can be swapped later.

// Inbound Port
export interface PayOrderUseCase {
  pay(orderId: string): Promise<string>;
}

// Outbound Ports
export interface OrderRepositoryPort {
  findById(orderId: string): Promise<any>;
  save(order: any): Promise<void>;
}

export interface PaymentProviderPort {
  charge(amountInCents: number, customerId: string): Promise<{ transactionId: string }>;
}

Connection to Design Patterns

Hexagonal architecture leverages several well-known design patterns:

Adapter Pattern

The classic Adapter Pattern is applied systematically here. Instead of isolated adapters, you build entire adapter layers for technical concerns like databases, HTTP, and messaging.

Strategy Pattern

Outbound ports define strategies for infrastructure access. The core works against the strategy interface, and concrete implementations can be swapped.

Dependency Injection

Hexagonal architecture relies on Dependency Injection. Adapters are injected into the core, not the other way around. This enables loose coupling and straightforward testing.

Facade Pattern

Inbound adapters can serve as facades for complex use cases. They encapsulate interaction with the domain core.

Coupling in Hexagonal Architecture

Tight Coupling (to Avoid)

Tight coupling occurs when business logic depends directly on concrete technologies. Switching databases or updating frameworks requires changes to the application core.

Loose Coupling (the Goal)

Hexagonal architecture enforces loose coupling through ports. The core knows only interfaces, not implementations. This enables:

  • Swapping adapters without touching the core
  • Parallel development of domain and infrastructure
  • Easy testing with mock implementations

Dependency Directions

Dependencies always point inward from outside. Adapters know the core through ports; the core knows nothing about adapters.

Typical Exam Questions (With Short Answers)

  1. What is the goal of hexagonal architecture? Decoupling business logic from technical details via ports and adapters.

  2. What is the difference between inbound and outbound adapters? Inbound adapters bring requests into the core; outbound adapters implement infrastructure access.

  3. How is Dependency Inversion applied here? The core defines ports (interfaces); infrastructure implements them.

  4. Why is this relevant for certification exams? You can justify architectural decisions with testability, maintainability, and interchangeability arguments.

  5. What role do ports play in testability? Ports allow mock implementations for unit tests without real infrastructure.

  6. How does hexagonal architecture differ from Clean Architecture? Hexagonal architecture is a specific approach within Clean Architecture focusing on ports and adapters.

  7. What happens when you switch databases in hexagonal architecture? Only the database adapter needs reimplementation; the domain core stays unchanged.

  8. What responsibility does an inbound adapter have? It receives external requests and forwards them to the domain core.

  9. What responsibility does an outbound adapter have? It implements technical interfaces for the domain core (database, HTTP, etc.).

  10. How is the Dependency Inversion Principle applied? The domain core defines interfaces; adapters implement them.

  11. What does “technology independence” mean? Business logic is independent of specific frameworks and databases.

  12. What are the drawbacks of hexagonal architecture? Higher initial effort, more abstraction layers, steeper learning curve.

  13. How many ports can an application have? Any number; typically one port per use case or per external interface.

  14. What is the difference between a port and an adapter? A port is the interface; an adapter is the concrete implementation.

  15. How is the domain core tested? Via mock adapters on ports, without real infrastructure components.

  16. Which frameworks support hexagonal architecture? Spring Boot, .NET Core, Node.js with dependency injection containers.

  17. What is a “hexagon” in this context? A symbolic representation of the domain core with ports on its sides.

  18. How are use cases modeled in hexagonal architecture? As inbound ports with corresponding implementations in the domain core.

  19. What kind of coupling is avoided? Tight coupling between business logic and technical implementations.

  20. How is the Adapter Pattern deployed here? Systematically for all external dependencies of the application.

  21. What are typical inbound adapters? REST controllers, GraphQL resolvers, CLI commands, message listeners.

  22. What are typical outbound adapters? Database repositories, HTTP clients, cache implementations, message producers.

  23. How does parallel development become possible? Domain core and adapters can be developed independently.

  24. What role does Dependency Injection play? It connects adapters to ports at runtime, enabling loose coupling.

  25. When is hexagonal architecture worth it? For long-term projects with frequent changes and high testing requirements.

  26. How are business rules protected? Through abstraction layers that prevent direct external access.

  27. What does “infrastructure doesn’t matter” mean? Business logic works independently of the chosen infrastructure.

  28. How do you integrate a new UI framework? By creating a new inbound adapter that uses existing ports.

  29. Which testing strategies are supported? Unit tests with mocks, integration tests with real adapters, end-to-end tests.

  30. How is maintainability improved? Through clear separation of business logic and technical details.

Important Data for Understanding

Historical Development

  • 2005: Alistair Cockburn coins the term “Hexagonal Architecture”
  • Alternative Names: Ports and Adapters Pattern
  • Goal: Protect business logic from technological changes

Core Principles

  • Dependency Inversion: dependencies flow from outside inward
  • Single Responsibility: each adapter has one technical concern
  • Open/Closed: ports are open for extension, closed for modification

Typical Project Sizes

  • Small to medium: 5–20 ports, 10–50 adapters
  • Large systems: 50+ ports, 100+ adapters
  • Microservices: 3–10 ports per service

Implementation Timeline

  • Initial effort: 20–30% more time than traditional architecture
  • Payoff: after 6–12 months through faster changes
  • Test speed: unit tests 10–100x faster than integration tests

Technology Support

  • Java: Spring Boot with @Component and @Autowired
  • .NET: Dependency Injection containers
  • TypeScript/Node.js: Inversify, TypeDI, or manual DI
  • Python: FastAPI with dependency injection

Success Criteria

  • Test coverage: >90% achievable in domain core
  • Change velocity: 50–80% faster implementation of new features
  • Maintenance costs: 30–50% lower than monolithic architectures

Common Mistakes

  • Too many ports: over-abstraction leads to complexity
  • Wrong boundaries: business logic leaked into adapters
  • Skipping tests: abandoning mock adapters reduces benefits

Hexagonal architecture shines when you prioritize long-term maintainability, solid tests, and technology independence.

Further Reading on This Topic

Hexagonal architecture builds on fundamental concepts of software development. Understanding the full potential of this pattern requires knowledge of related areas. Design Patterns form the foundation for many architectural approaches, while solid software design principles support decision-making when choosing appropriate architectures. The following articles help you learn the necessary foundations and understand hexagonal architecture in the context of modern software development.

Architecture and Design Patterns

Software Architecture and Design

Practical Application

Back to Blog
Share:

Nächster Artikel in Software Architecture

Weiterlesen
HTTP Idempotency Explained: Rules & Status Codes

Related Posts