Sitemap
iyzico.engineering

The engineering behind iyzico, the sweet home for iyzicoders…

Hexagonal Architecture: Building Maintainable Systems with Ports and Adapters

5 min readJun 16, 2025

--

Change in the software world is accelerating rapidly. Today, systems are becoming increasingly complex and the need for flexible and sustainable architectures is increasing. At this point, hexagonal architecture goes beyond traditional approaches and brings a breath of fresh air to the software world.

Hexagonal Architecture: The Golden Cage of Software

Hexagonal architecture, introduced by Alistair Cockburn in 2005, treats business logic as a precious jewel that needs protection from external complexities.

This architectural pattern ensures applications can be equally accessed through multiple interfaces (whether by users, other programs, automated tests or command-line tools) while remaining completely unaware of how they’re being used.

The software maintains independence from runtime infrastructure components like databases, caches, servers, and REST APIs, allowing for flexible development and deployment.

Separation of Concerns: Clarity Through Structure

As software systems grow, complexity becomes inevitable. One of the most effective ways to manage this complexity is through the principle of Separation of Concerns (SoC). At its core, SoC means organizing code so that each module, class, or layer focuses on a single responsibility or concern, without overlapping with others.

Press enter or click to view image in full size

In practical terms, this means keeping business logic separate from infrastructure code, UI separate from data access, and domain models separate from persistence logic. Each concern is isolated, which makes the system easier to understand, develop, test, and modify.

This clear separation is what gives hexagonal systems their robustness and adaptability — every layer has one job, and does it well.

Dependency Inversion Principle: The Core Idea

Maintaining flexibility and adaptability is key. One common pitfall teams face is tightly coupling high-level business logic with low-level implementation details. This often results in brittle systems that are difficult to change or extend.

The Dependency Inversion Principle (DIP) provides a solution by encouraging the inversion of traditional dependencies. The direction of dependencies is from higher level modules to lower level modules. These dependencies should be made with well-defined abstractions. DIP encourages a clean separation of concerns, resulting in systems that are easier to maintain, test and improve over time.

Press enter or click to view image in full size

High-level modules represent the core logic and business rules of your application. They define “what” the system should do, often in the form of use cases, services, or application workflows. These modules are intended to be stable and long-lived, and they should remain unaffected by technical details or infrastructure changes. The domain layer is high-level module.

Low-level modules are responsible for “how” the system accomplishes tasks. These are technical, infrastructure-focused components that interact with databases, web APIs, file systems, or messaging systems. Because technologies change more frequently than business rules, these modules are typically more volatile. The infrastructure layer is low-level module.

Business Logic Layer: Core Domain

The domain layer contains the application’s business rules, domain models, workflows and use cases. This layer is the heart of the application and is completely independent from the outside world.

Core: Business logic and domain models are defined here. For example, in an e-commerce application, models such as Order, Product, Customer are in the Core.
Use Cases: Implement the business rules and workflows of the Domain layer.Defines the business scenarios. Each use case represents a specific user interaction or business process. For example: CreateOrderUseCase.
Ports: Abstract interfaces that define how the Core communicates with the outside. For example: PaymentPort, BalancePort.

Press enter or click to view image in full size

Infrastructure Layer: External World

The infrastructure contains the concrete applications that enable the Domain layer to communicate with the outside world. This layer is dependent on the Domain layer and fulfills its needs.

Adapters: They are concrete implementations of ports. They act as a bridge between the Domain layer and external systems. For example: BalanceDataAdapter.

Framework dependencies and configurations, external system clients, db dependencies, message brokers, rest apis etc. are managed here. This layer is where the application manages incoming and outgoing requests from the outside

The Only Constant in Life Is Change

Customer expectations evolve, technologies advance, business rules get updated. In poorly designed systems, these changes create a domino effect — a modification in one point reverberates through every corner of the system.

Get İsmail Müezzinoğlu’s stories in your inbox

Join Medium for free to get updates from this writer.

Hexagonal architecture offers an elegant solution to this challenge. By protecting your business logic from the chaos of change, it makes your system ready for evolution. For example:

  • Need to switch your database? Just update the relevant adapter.
  • Integrating a new payment system? Add a new adapter.
  • Moving from REST API to GraphQL? Create a new adapter without touching your existing business logic.

In each case, your valuable business logic remains isolated from these changes. This provides software teams with incredible freedom and confidence. You can implement technological changes without risking your business logic.

This approach doesn’t offer you systems that are “resistant to change,” but rather systems that are “ready for change.” Because in the modern software world, success lies not in preventing change, but in embracing it.

Perfect Harmony with Domain-Driven Design

Hexagonal architecture demonstrates perfect harmony with Domain-Driven Design (DDD) principles. By putting business logic at the center, it enables more effective communication with domain experts. While technical details remain in the background, business processes and rules come to the forefront.

Testability: The Key to Safe Change

One of the strongest aspects of hexagonal architecture is its superiority in testability. Since external dependencies (database, rest, queues, etc.) are removed, business logic can be tested more easily.

The tests will test real business logic. External dependencies will not have to be mocked. The need to use testcontainers will be much reduced as it will be done only on the infrastructure side.

Thus, the tests will run much more efficiently. Application uptime will be dramatically improved.

Points to Consider

Although hexagonal architecture offers powerful advantages, the architecture alone is not a magic wand. It needs to be used carefully.

  • Does your project’s size and complexity require this architecture? It might be overkill for small projects.
  • Software development is a team work. Make sure the team is ready for this architecture and has enough knowledge.
  • The domain layer should always be the priority. Don’t allow business logic to leak into the infrastructure layer.
  • Ensure Consistent Port Definitions. Clearly define and maintain consistency in your ports (interfaces) to prevent confusion and ensure seamless communication between the core domain and external systems.

Conclusion

Hexagonal architecture offers an elegant solution to the complex requirements of the modern software world. It enables you to develop systems open to change and sustainable while protecting your business logic. However, like any architecture, it finds its value when used in the right projects and in the right way.

If you’re developing systems with complex business logic that are long-lived and continuously evolving, hexagonal architecture can provide you with a strong foundation. The key is to adapt this architecture according to your project’s requirements and your team’s capabilities.

Recommended resources:

--

--