Have fun learning about Test-Driven Development with JitterTed's TDD Game

Event Bus: Inside or Outside the Hexagon?

Where does a Message/Event Bus belong in Hexagonal Architecture?


Diagram of a hexagonal architecture, which contains Application Layer and Domain Layer inside the hexagon, and adapters on the outside
Hexagonal Architecture: The Hexagon

Q. In Hexagonal Architecture, where does a Message/Event Bus belong?

A. It depends! (Because of course it does.)

In Hexagonal Architecture, we can often rely on the question of: “does it do I/O to support its work or run out-of-process?” If not, then it can live inside the Hexagon, otherwise it’s on the outside (in adapters). Note that you need to include all of its dependencies when answering this question.

Examples

In-Process EventBus

You want to use a library to do lightweight Domain Events publishing. The code is in a single EventBus Jar[1], and it doesn’t do any I/O, nor any out-of-process communication. All events are “broadcast” to listeners by calling methods defined in a Listener interface (aka the Observer Pattern) as they happen. As long as it is easy to instantiate and Test-Double the EventBus (for testability, of course!), then it can go inside the Hexagon.

Spring Framework’s Event Publisher

You want to take advantage of Spring’s Application Event support. In order to publish an event, you need a reference to an ApplicationEventPublisher, which is in Spring’s context module. This brings in the Spring Framework as a dependency, and, well, that means it cannot go inside the Hexagon.

Async Job Runner

What about JobRunr? It’s a dedicated library for running jobs asynchronously, on a regular schedule, etc. Usually you would use it with a real database (for persistence and potential scaling), but you can run it with an InMemoryStorageProvider. Technically, you might be able to run it within the Hexagon, but it’s complex enough—and deals with concurrency/threads—that I’d push it outside the Hexagon. I’d use an Outbound Port to initiate scheduling jobs, and an Inbound Adapter to handle execution of scheduled jobs. Since a mere configuration change could cause it to depend on a real database, that would completely eliminate it from running inside the Hexagon.


  1. Note: Guava’s EventBus is now recommended not to be used. I found this out when I was looking at using an in-memory/in-process event bus. See the EventBus API page for details. ↩︎


Make Your Code More Testable™️

Don't miss out on ways to make your code more testable. Hear about new Refactoring techniques, improving the Test-Driven Development process, Hexagonal Architecture, and much more.

    We respect your privacy. Unsubscribe at any time.