Optivem Journal

Optivem Journal

Hexagonal Architecture

Hexagonal Architecture - External World (The "outside")

Our system interacts with the external world through adapters

Valentina Jemuović's avatar
Valentina Jemuović
Nov 07, 2025
∙ Paid

The Outside of the Hexagon

The “external world” contains all the technologies and systems that surround our core application: databases, APIs, message brokers, user interfaces, etc.

The hexagon acts as a shield - it defines a clear boundary between what’s inside (domain and use cases) and what’s outside (infrastructure and delivery).

The outside world can change - you might switch frameworks, UIs, or databases - without changing the core logic inside the hexagon.

That’s because communication between the two happens only through ports and adapters.

Driving Adapters (User-side API)

On the left side of the hexagon, we have Driving Adapters — these are the entry points that drive the application from the outside.

They present the application in a way suitable for clients, and then call the driving ports (the use cases).

Driving adapters - examples:

  • A REST API that receives HTTP requests and calls a use case

  • A Web UI or mobile app interacting with backend services

  • A command-line or batch process triggering operations

Driving adapters don’t contain business logic. Instead they contain presentation logic:

  • Receive external input (like an HTTP request or button click)

  • Convert it into a suitable format (e.g. a DTO)

  • Call the appropriate use case inside the hexagon

  • Return the result back to the client

Driving adapters make it possible to expose the same use case in multiple ways — e.g. through a web API, CLI, or message consumer — without duplicating logic.

You can swap out your web framework or migrate from REST to GraphQL without touching your business rules.

Driven Adapters (Server-side API)

On the opposite side of the hexagon, we have Driven Adapters — these implement the driven ports that the application depends on.

If a use case needs to:

  • Save data to a database

  • Call an external API

  • Send an email

  • Publish an event

…it doesn’t do those things directly. Instead, it talks to a driven port interface, and the driven adapter handles the infrastructure details.

Driven Adapters - examples:

  • Database Adapter implementing OrderRepository interface, e.g. by executing SQL queries on an SQL database, or perhaps by using an ORM, etc.

  • Email Adapter implementing NotificationGateway interface, e.g. by using Gmail SDK to send emails

  • Payment Adapter implementing PaymentGateway, e.g. by integrating with Stripe or PayPal API

  • Event Adapter implementing PublisherGateway, e.g. by publishing messages to Kafka or RabbitMQ

Driven adapters keep infrastructure concerns separate from business logic.

If your database, API provider, or message broker changes, you only update the adapter — your domain and use cases remain untouched.

Real-life Example: Ordering System

This post is for paid subscribers

Already a paid subscriber? Sign in
© 2025 Valentina Jemuović, Optivem
Privacy ∙ Terms ∙ Collection notice
Start your SubstackGet the app
Substack is the home for great culture