CodeIntermediate

Layered vs hexagonal architecture

“Compare layered architecture with hexagonal (ports and adapters). What problem does hexagonal solve that layers do not, and when is the difference not worth the extra structure?”

What this tests

  • Understanding of dependency direction, not just layer names
  • Whether the candidate knows the concrete problem hexagonal solves (domain depending on infrastructure)
  • Testability as a consequence of structure
  • Judgment about when the extra abstraction is not paid for

Answers by level

Read the beginner answer first and notice what is missing.

In a classic layered stack the arrows point down: controller → service → repository → database driver. The problem is that the domain layer ends up depending on the infrastructure layer, so business rules import the ORM, the tests need a database, and swapping the storage means editing the domain. Hexagonal inverts that one arrow: the domain defines a port (an interface such as OrderRepository), and the database adapter implements it. All dependencies point at the domain.

What that buys is concrete: the domain compiles without the database, a unit test injects an in-memory adapter and runs in milliseconds, and the same domain can be driven by a REST controller, a queue consumer or a CLI without change. The cost is the interface and the wiring: an extra type per external dependency and a composition root that assembles adapters.

For a CRUD service with little business logic, the domain is thin and the ports mostly wrap a repository one-to-one; the interfaces then add files without adding safety. Layers with a rule that the domain does not import the driver get most of the benefit.

Green flags · Red flags

Strong green flag · Says the port pays off when there is more than one real adapter or an unstable external dependency.
Green flags
  • Explains the difference as dependency direction, not box arrangement
  • Names the concrete failure: domain importing the ORM or driver
  • Ties ports to testability with in-memory adapters
  • States when the abstraction is not worth it (thin CRUD)
  • Mentions enforcing the rule in CI
Red flags
  • "Hexagonal is more modern, so use it for everything."
  • Cannot say which way the arrow points between domain and repository
  • Thinks layers are about folder names
  • Adds interfaces with exactly one implementation everywhere and calls that decoupling

Follow-up questions

F1
Show me the one arrow hexagonal reverses.
F2
How do you test a use case without a database?
F3
When would you strip the ports out of an existing service?

Scenario

A team has a "clean" service with 40 interfaces, each with exactly one implementation, and unit tests that mock every repository to return canned rows. The domain has almost no logic; most bugs are in SQL. Propose a structure that keeps testability where it matters and removes what does not pay.

Learn this topic