Sponsor: Do you build complex software systems? See how NServiceBus makes it easier to design, build, and manage software systems that use message queues to achieve loose coupling. Get started for free.
What is event sourcing? Many terms are often used that can be pretty confusing. I will explain the core concepts and, specifically, Event Sourcing terminology so you can better understand what it is and what some of the benefits might be.
YouTube
Check out my YouTube channel, where I post all kinds of content accompanying my posts, including this video showing everything in this post.
Events
At the heart of event sourcing are events. Events are statements of fact. Events are records of things that have happened within your system and your domain. They represent facts that provide insight into the state of your application at any given point in time.
For instance, consider a warehouse management system. Each event is named in the past tense to signify that it has already occurred, capturing a specific business fact. For example:
- Product Received: 10 units received on a specific date.
- Product Shipped: 5 units were received a couple of days later.
- Produt Shipped: 6 units were shipped a few days later.
- Inventory Adjustment: Adjusted quantity a day later because a stock count occurred and more units were found.
- Past Tense Naming: Events are named in the past tense, reflecting that something has already occurred. This naming convention helps clearly identify the event’s nature as a business fact.
- Business Facts: Each event encapsulates the information significant to the business, including the details of what happened, when it occurred, and potentially additional metadata.
Events form the backbone of event sourcing, as they provide all the information needed to reconstruct the state of the application at any point in time.
Event Streams
Events are typically organized into event streams. An event stream is a collection of related events that pertain to a specific entity or aggregate, such as an inventory item. Each product could have its own stream, allowing you to track all related actions over time. The events within a stream are sequenced, preserving the order in which they occur, which is crucial for reconstructing the system’s state at any point in time.
- Modeling Event Streams: The way you define your event streams often depends on the domain model you are using. You may model them around aggregates.
- Lifecycle Considerations: Streams can have varying lifecycles; some may be long-lived with fewer events, while others may be short-lived with a larger number of events.
Understanding how to properly define and utilize event streams is crucial for effective event sourcing.
Projections (Read Models)
While events provide a historical record, applications often need to derive current state information. This is where projections come into play. A projection is a transformation of the event stream into a format that is useful for querying or reporting.
Deriving Current State: For instance, if you want to know the current quantity of a product on hand, you would process the entire event stream and apply each event to calculate the current quantity.
Use Cases for Projections: Projections can be tailored for different use cases, such as generating reports or providing data to a user interface.
Projections can be stored in various formats, including relational databases, document stores, or caches, depending on the specific requirements of the application.
They can even be used to create new event streams. A typical scenario is to create new event streams that represent a summary, which can be the start and continuation of a new event stream. This is different from a snapshot.
Projections (Write Models)
In addition to read models, projections can also serve write models. When executing an action that modifies state, often referred to as a Command, such as shipping a product, the application must verify that the action is valid based on the current state.
By reading the event stream, the application can derive the necessary state to determine if the action can proceed. This ensures that business rules are enforced.
Typically, a projection is built within an Aggregate at runtime in memory to force optimistic concurrency. When appending new events to an event stream, optimistic concurrency can verify that the event stream is in the same position it was when it was read to build the projection.
Subscriptions
To keep your read models up to date, you can use subscriptions. Subscriptions allow different parts of your system to react to new events as they occur. For example, when an event is appended to an event stream, a subscriber can listen for that event, perform any necessary transformations, and update the read model accordingly. This reactive approach ensures that your application remains consistent and responsive.
Projectors: By implementing event listeners, application components can react to changes in the event stream and update their projections (read models).
Inter-System Communication: Subscriptions can also facilitate communication between different systems, allowing them to respond to relevant events without tight coupling.
It is worth noting that subscriptions depend on the tooling/database you’re using to persist your event streams. Some might have more polling mechanisms vs push.
Event Sourcing Terminology
Event sourcing revolves around recording facts that occurred in your system and utilizing these events to derive meaningful states. By understanding event sourcing terminology around the concepts of events, event streams, projections, and subscriptions, you can leverage event sourcing to build robust systems. If you’re interested in diving deeper into event sourcing or software architecture, consider joining my online community and accessing my private discord, where you can chat with other like-minded software developers.
Join CodeOpinon!
Developer-level members of my Patreon or YouTube channel get access to a private Discord server to chat with other developers about Software Architecture and Design and access to source code for any working demo application I post on my blog or YouTube. Check out my Patreon or YouTube Membership for more info.