zachdaniel
AshEvents: Event Sourcing Made Simple For Ash
Hey folks!
AshEvents Release
We’ve just released the first version of AshEvents, an Event Sourcing tool for Ash Framework apps.
Check out the blog post for the announcement! Thanks to @Torkan for building this package and for writing a guest post for the Alembic blog to share!
AshEvents: Event Sourcing Made Simple For Ash — Alembic ![]()

Most Liked
vasspilka
Hello, since EventSourcing has been a really important stepping stone in my career and I’ve invested significant time to understand and implement it I want to throw in my 2 cents. First I should note that I may be biased, but in my head EventSourcing (ES) and Domain Driven Design (DDD) are linked, even though one may use ES without DDD or DDD without ES they only have substantial impact when together. Without DDD, ES can be easily replaced with CDC (Change Data Capture) having less effort and effectively the same benefits. As such when I mention ES, it is assumed DDD is present.
I’ve done some form of ES in 4 companies so far, of which I must say only 1 saw substantial benefits using it, the other 3 had almost no benefit and in some cases I would argue it slightly hurt them. The reason? The business did not care for ES (even though they hired engineers to implement it).
The longer I’ve been working with EventSourcing and CQRS the more it has been becoming clearer that it’s not primarily a software architecture per say (even though it certainly is one) but rather it’s a business strategy. To successfully implement it you need you need 3 things ordered by importance:
- A complex domain and Domain experts who understand it
- Business who sees ES as their competitive advantage
- A technical implementation
ES exists to deal with complex problems, it’s a slow and steady approach. Technically we present the benefits of ES as enforced audit-log, async communication, having a time-machine and the ability to recreate state. But in fact the main benefit is the ability to handle ever increasing complexity on a logarithmic curve. Dealing with domain complexity however is not an engineering problem, it’s a business problem. ES/DDD requires a change in the methodology of how software is build, and it must start from the top, the business has to become an active part in designing the software, and that is done though defining Events and how they affect the state of the application.
So getting back to the subject of Ash Events, I think it’s a cool addition to the Ash ecosystem, but overall I don’t find that it will help businesses who want to adopt an ES/DDD strategy. Ash is pretty opinionated on how software is build (through Resources and Actions) that’s a far cry from Events, Aggregates and Handlers. The “Ash way” does not push you towards the change in methodology for building ES software, rather it makes it easier to write declarative resource oriented software (which is amazing in it’s own right).
In contrast, let’s take a look on Commanded, an ES/CQRS framework, it is also very opinionated, however it “pushes” you toward thinking about Events and how they affect the state of your application as the primary concern. Now don’t get me wrong, Commanded as any framework has it’s drawbacks, there are many times I found it was getting in the way of what we designed as a business, but with even with it’s flaws the intent on focusing on the right thing was there.
So in my opinion the “Ash way” is very different than the “ES/DD way” and I would not recommend it for a business that has decided to do ES. Nonetheless I am sure people will make use of some of the features AshEvents will provide to applications doing the Ash way.
All that being said I love Ash and it’s declarative way of doing things. That’s exacly why I choose to do my startup in Ash, “ES/DDD” is only really worth it when a particular business needs it.
tcoopman
Some disclaimers before my post:
- I haven’t read all of the above in detail
- I don’t really know Ash expect for that there is so much noise and movement around it that I almost have FOMO for not trying it out

- I consider myself a DDD expert - it’s my job
Having that out of the way, I’d like to make 2 additions:
Firstly, I agree that event sourcing doesn’t say anything about storing state. The only requirement is that you can make new decisions based on the history of what happened. Technically this means that you can rebuild your state from the history of events.
So as long as you store your state and events in the same transaction this is fine if you take care of the following: making sure your events are complete.
If you first build your state and then build the event, you have risk that you forgot to put some attributes on the events, meaning you wouldn’t be able to reconstruct the state accurately.
That’s why in event sourcing we most often have the pattern where we apply the events in order to build the state. That guarantees that our events are complete.
Secondly, about DDD and event sourcing. Sure they are often used together, but they don’t require each other. You can do DDD without event sourcing and the other way around as well.
I would like to add that the value of event sourcing of indeed comes from the fact if your business has any value in storing what actually happened.
A trivial example, is the difference of AddressUpdated vs PersonRelocated relevant for you?
Or StockUpdated vs ItemScannedIn and StockManuallyCorrected?
If you (or your business - hopefully you are aligned on this
) don’t care about this difference, then event sourcing will probably not add a lot of value and not be the best choice.
In my opinion though I’ve noticed a lot of complex domains where these kinds of things are very relevant and offer great value to the teams building this. But of course there are downsides as well, so do your own research and understand why building something event sourcing would be valuable for your software.
(Last small remark - you don’t need to apply event sourcing to your full architecture/product, maybe it’s only useful for some complex parts, and the other parts are fine with CRUD/…)
This turned out a bit longer than I had in mind, hopefully it’s useful for someone!
zachdaniel
The term may not be as strictly defined as you think ![]()
Lets cite some sources:
The fundamental idea of Event Sourcing is that of ensuring every change to the state of an application is captured in an event object, and that these event objects are themselves stored in the sequence they were applied for the same lifetime as the application state itself.
There are a lot of ways to interpret and implement the concept of “event sourcing”, but the most important property is that you can delete all of the projections from the event store, and then rebuild them all by playing forward an event log.
AshEvents has this property. What we’re doing, however, is persisting to the projections directly while persisting to the authoritative event log, which is just an implementation detail.
Could you perhaps restate this in terms of a concrete benefit that you get by having events as “primary” and state as “secondary”? Like a capability of an application that you have by doing that that you don’t have if you don’t do that? Regardless, I’d say that AshEvents is not putting one first or second, it is a middle-ground design pattern that gets you the best of both worlds (if you’re willing to adopt some constraints).
I think it’s very reasonable to invert the pattern that AshEvents uses, and would not take a significant amount of change to implement it. What we would do is add a piece of context that is set that tells us to actually run any hooks on an action, and default it to false. Then you can hook something up to your event resource (something like EventStore — EventStore v1.4.8) that runs it on a loop and reruns that event with that context set to true.
Ultimately, there is just no need for us to add that layer of indirection to have all of the same benefits. But if someone else wants it, then PRs welcome ![]()
What we’re going for is not having to restructure the entire application like an event stream/handler system (often putting side effects far away from their cause, and making understanding a system without “just running it and finding out” really difficult) to get the benefits of event sourcing.
While I appreciate the concept, I definitely wouldn’t intentionally misuse a technical term just for marketing purposes
. If someone convinced me well enough that this really doesn’t qualify as event sourcing (i.e by no definition of the term does it fit), then I’ll happily ensure the blog post is updated.
vasspilka
Hey,
So as per my earlier post I think the main advantage of ES (when coupled with DDD) is the shift in how software is designed and modeled.
I like to compare it a bit to the shift of mindset in functional immutable programming and OOP (though it’s in fact it’s a quite different comparison), the former can handle increasing complexity on a smoother curve than the latter. Let’s see why.
When you are handling state in a traditional application you really don’t know how/why that state got there, for all you know someone might have went to the production database and updated a couple of rows of data. In other words the application state is itself “The source of truth” but the problem with that you don’t know how it got to that state, ofcourse you can have audit logs, transactional tables etc, but at the end most applications will not store all data changes as some audit log. This results in a situation where you can’t be sure why a specific applications state has the value it has.
ES flips that around, it sais the “audit log” or better yet event log, is the source of truth, it’s an immutable append only database and the application state is derived from that log (not all application state must be ES). This offers the advantages that now you know why a specific state is what it is, and if not you can fix it. Also you can decide to construct a new state or update existing state based on that event log.
Let’s see in practice how can that work. You are a fintech company, your core domain is dealing with financial transactions, this may be double entry accounting, but also higher level actions like, “Account opened/closed”, “Contract Signed”, “Invoice Generated”, etc… Now all these actions might have multiple sideeffects on your end state, like for example “Invoice Generated” might create credit/debit pairs and create add an invoice row, “Account Closed” might delete some rows from your database and update the customer etc. With ES not only you can reason about why your state is in the state it is. But also create new state from historical data. For example you might decide that you can to create a Loan Tape (a dataset that contains information about a pool of loans) for everything that happened since the beggining of 2023. With ES you simply write a new projector tell it when to start and handle all the events since then to create your new state. This can be for any type of data, you could build an XSL or calculate metrics for a presentation, maybe you want to know what’s the percentage of people that have closed their account within 2 months that a contract was signed, and you want to calculate that for data going back 3 years. That is the power of ES.
It’s not recreating your existing state, but creating new state that you don’t even have.
But as previously mentioned, you need the business to support you in modeling the software this way, it does not work just as an engineering solution, you need the business to actively work on modeling the events and how they contrsuct the application state.
zachdaniel
To be clear: this is like saying “I think you can have ES and Phoenix Contexts separately in the same application”. You can model any external or internal paradigm with Ash resources. This is not obvious on the tin, I understand that, but I do want to make it clear. You could use Ash and commanded side by side if you wanted. Ash actions that create events etc.
Ash does not even require that you ever use it to map to a storage layer. This is a valid resource:
defmodule Something do
use Ash.Resource
actions do
action :say_hello, :string do
{:ok, "Hello"}
end
end
end
That Ash is about state management or fits in as an ORM primarily is generally the most common misconception about Ash.







