What are you building your event-driven elixir systems on?

There are a number of ways to go about building an event-driven system in Elixir and which exactly you’re using depends on the needs of the application you’re building. This thread is meant to get a “lay of the land” for which tools the community likes to reach for.

To get us started here are some options I’ve seen mentioned in the wild:

What is your weapon of choice and why? Are you beginning with something simple and replace it with something else when the scale demands it? How do you structure your application when building a system like this and why?

3 Likes

“It depends.” When it comes to messaging in Elixir there’s so many ways to approach it so there’s a suite of options.

Registry/PubSub are good for transient consumers with weaker guarantees. A liveview or channel can subscribe and the pubsub semantics deliver the message but if that Liveview session gets killed / disconnected: not a big deal. So a good tool for natural OTP process <> process delivery - just handle_info callbacks and a simple interface for topics.

Genstage/Broadway are good for high throughput data pipelines and in a classic CQRS model are usually more seen in either command handling or projection/read-model construction.

I would also look at Eventstore and some of the Commanded tooling on top. In most workflows where pubsub is used you still need a persistent model and eventstore gives you a way to persist each event and deliver to n subscribers. The persistent stream interface has more going on than Phoenix PubSub, but it lets you revive a state machine by reading past events and rebuilding state.

After you have a persistent model of some kind, you might want to push that event to a messaging system or queue like RabbitMQ/SQS/Kakfa/etc either for integration to another system or to buffer some expensive data pipeline operation. Broadway in particular builds on Genstage to provide a high level tool to control for load and throughput such as to accumulate a set of “things to insert_all” into a database and prevent overload against potential bottleneck or protected resource like your reporting database.

Finally you might have those integration events that go out to external systems - this is where something like webhooks, Kafka, RabbitMQ streams, or some kind of high throughput messaging system with pubsub semantics, good subscriber guarantees and widespread client library support is good.

So all of the above when it depends.

2 Likes

If I were to build the whole app around events and reacting to them (which is a great way to build an app!), I would probably use Commanded on top of PostgreSQL (personal preference, I don’t like Event Store).

For just having an event bus to do some things reactively (and async) – event_bus package you mentioned looks great. Although I don’t have real experience with it.

For just organizing the codebase, you can just as well use a synchronous/inline event dispatcher, as described here or (shameless plug) here.

1 Like