Event driven vs Event sourcing
· Domain Events
· Event-driven architectures [EDA]
· Event sourcing
link for all System design articles
Domain Events
- In domain-driven design, domain events are described as something that happens in the domain and is important to domain experts.
- Such events typically occur regardless of whether or to what extent the domain is implemented in a software system. They are also independent of technologies.
- Accordingly, domain events have high-value semantics, which are expressed in the language spoken by domain experts. Examples can be:
1️⃣ A user has registered
2️⃣ An order has been received
3️⃣ The payment deadline has expired - Domain events are relevant both within a bounded context(A bounded context is simply the boundary within a domain where a particular domain model applies) and across bounded contexts for implementing processes within the domain.
- Domain events are also ideally suited to inform other bounded contexts about specific business-related events that have occurred in their own bounded context and thus to integrate several bounded contexts in an event-driven way.
Event-driven architectures [EDA]
Event Driven Architecture is about components communicating via publishing events rather than making (e.g.) RPC calls against each other or manipulating shared state. It’s a communication strategy (albeit one which often relies on messages being persisted for fairly long periods).
- The term “event-driven architecture” refers to any software system in which components communicate primarily or solely via events.
- The production, detection, consumption, and reaction to events are all promoted by this software design paradigm.
- A significant change in status can be regarded as an event.
- The term “event” usually refers to “notification” in the context of EDAs
- Event-driven architecture is a distributed asynchronous architecture pattern used to produce highly scalable applications.
- For example, consider a shopping cart service backed by a relational DB. The cart is represented in the DB by a row in a
carts
table and acartitems
the table represents tracks has rows that say "2 USB chargers in cart ABC with price $4.75 apiece". To add items to the cart we insert (or update if it's just a quantity change) rows to thecartitems
table. When the cart is checked out, we publish a JSON representation of the cart and its contents so the shipping service has what's in the cart and we setcarts.checked_out
toTRUE
.
→ That’s a perfectly OK Event-Driven Architecture. The cart service communicates that there’s a checked out cart to the shipping service. It’s not event-sourced: we can’t reconstruct the DB from the events.
Event sourcing
Event Sourcing ensures that all changes to application state are stored as a sequence of events.
Event Sourcing is when the components themselves treat the history of events which they have persisted as the ultimate source of truth for their state (or at least the state that they actually care about).
It’s a persistence strategy and doesn’t intrinsically say anything about communication.
The persisted events being the ultimate source of truth implies that an event replay recovers the state (by definition, if an event replay could not recover the state, then the events were not the ultimate source of truth).
- Instead of storing the current state within the application directly field by field in a table in the database, reloading it when needed, and overwriting it by subsequent changes, a chronologically ordered list of events is persisted, which can then be used to reconstruct the current state in memory, if necessary.
- Transactional database systems, which keep any state changes in a transaction log, are a well-known popular class of examples.
- The term “event” here refers to “state change” rather than “notification.”
- The state is saved as a sequence of events at a location known as the event store.
- New events are added to the list, but they do not replace existing ones. As a result, the entire history is preserved.
- The log of events in an Event Sourced component is a very good (I’d even suggest that it’s the optimal) source for deriving events to publish in an Event-Driven Architecture, so Event Sourced components can be a part of an Event-Driven Architecture.
Example: The shopping cart service could be event sourced. It stores events in an event store (which could be a datastore designed for the needs of event sourcing or could be relational DB or non-relational DB being used in a particular way (e.g. an events
table)). The following sequence of events for cart ABC might be written to the event store:
- AddItem { “USB charger”, $4.95 }
- AddItem { “USB charger”, $4.95 }
- AddItem { “Camel Book”, $34.95 }
- RemoveItem { “Camel Book” }
- DiscountApplied { Requirement { 2, “USB charger” }, -$0.40 }
- AddItem { “The C Programming Language”, $19.95 }
- CheckedOut { Items { Item { “USB Charger”, 2, $4.75 }, Item { “The C Programming Language”, 1, $19.95 } } }
→ That last event (along with the fact that it’s for cart ABC, which is metadata associated with the event) can be used to derive an event for publishing. One key thing to note is that there’s nothing else being written to the DB but these events.
As far as Event-Driven Architecture is concerned, these two cart services are basically the same: they publish the same checkout events. That one is event sourced is really just an implementation detail of that service.
Benefits of event sourcing
- 100% accurate audit logging — Auditing functionality is often added as an afterthought, resulting in an inherent risk of incompleteness. With event sourcing, each state change corresponds to one or more events, providing 100% accurate audit logging.
- Easy temporal queries — Because event sourcing maintains the complete history of each business object, implementing temporal queries and reconstructing the historical state of an entity is straightforward.