Hexagonal architecture diagrams

Ports and adapters, drawn as the shape the pattern is named after.

Hexagonal architecture, or ports and adapters, puts domain logic at the centre and pushes every external dependency to an adapter at the edge. The diagram is worth drawing because the pattern's whole claim is about which direction dependencies point, and that is exactly what prose obscures.

When to use these

When not to

Common mistakes

The usual failure is an adapter that has leaked domain logic into it, or a port defined in terms of the technology behind it rather than what the domain needs. If your port is called `UserRepository` and has a `findBySqlQuery` method, the dependency is pointing the wrong way.

The 3 templates

Hexagonal Service.puml

One service, its ports and its adapters.

Hexagonal Service: rendered example
Show the source
@starthex
Title("Order Service")
Domain("Domain")
Module("Order · LineItem")
Module("Place / Cancel")
Driving("Consumer", "REST API")
Driven("Order Repo", "PostgreSQL")
@endhex

Notes and a copy button for this template

Hexagonal Application (concentric).puml

Concentric view: domain, application, infrastructure.

Hexagonal Application (concentric): rendered example
Show the source
@starthex
Title("Commerce Platform")
Domain("Domain")
Module("Orders")
Module("Inventory")
Module("Payments")
Module("Shipping")
Driving("Web App", "REST API")
Driving("Mobile App", "REST API")
Driving("Ops Console", "Admin UI")
Driven("Payment adapter", "Card Processor")
Driven("Email adapter", "Email Provider")
Driven("Repository", "SQL Database")
@endhex

Notes and a copy button for this template

Multi-domain (integration).puml

Several hexagons and the contracts between them.

Multi-domain (integration): rendered example
Show the source
@starthex
Channel("order.placed")

Service(orders, "Order Service") {
  Domain("Ordering")
  Module("Cart")
  Module("Checkout")
  Driving("Consumer", "REST API")
  Publish("order.placed", "Event Publisher")
}

Service(shipping, "Shipping Service") {
  Domain("Shipping")
  Module("Dispatch")
  Module("Tracking")
  Consume("order.placed", "Event Handler")
  Driven("Repository", "SQL Database")
}
@endhex

Notes and a copy button for this template

Render these offline

Every template here ships in Gnomon and renders on your machine, with no account and nothing sent to a server. The browser editor is free and needs no install.

Get GnomonOpen the browser editor