Event Sourcing - System Design

What is Event?
Event is about actions performed by users in system. In event sourcing, an event is simply a record of something important that has happened in the system. Think of it like a journal entry. Each entry tells you exactly what happened, and in what order.
Imagine you have an online shopping cart:
When you click the "Add to Cart" button for a product, that's an event: "Product Added to Cart".
When you proceed to checkout, that's another event: "Checkout Initiated".
So, events are like these actions or changes that are saved as a history. Instead of just updating the cart's state, you record each step that led to that state. This history is the source of truth, and you can always rebuild the current cart state by replaying these events in order.
These events are processed by actions performed in database. We take the events as the source of truth. In the conventional world of system design, applications interact with a database through atomic, CRUD-based operations. We insert, update, and delete — directly modifying the current state of the system. This approach works well for many use cases, but begins to crack when faced with concurrency, auditability, or recovery demands. Consider a financial platform handling thousands of operations per second — updating balances, processing payments, and logging user activity. What happens when two users initiate conflicting actions simultaneously? How do we recover from a corrupted update? Where is the trace of what truly happened?
This is where Event Sourcing brings an architectural paradigm shift.
Why Traditional State Mutation Falls Short
In traditional systems, we store the latest state of an entity. Let’s take the case of a banking application. Suppose a user has a balance of ₹5,000. If they deposit ₹2,000, the system directly updates the balance to ₹7,000:
UPDATE accounts SET balance = 7000 WHERE user_id = 101;
This operation is atomic and destructive. It tells us nothing about:
When the deposit happened.
Who initiated it.
Whether any intermediate operations were attempted.
If this update collides with a concurrent withdrawal transaction, the result may be incorrect — either the transaction is lost, or the final balance becomes inconsistent. Moreover, there's no reliable way to reconstruct the account history or reverse a bad update.
The Shift to Event Sourcing: Events as the Source of Truth
Event Sourcing flips this model on its head.
Instead of saving the current state, we store a series of events that represent each change that has occurred to the system.
In our banking example, this means we no longer overwrite the balance column. Instead, we append a deposit event to an Event Log, like:
{ "type": "DEPOSIT", "amount": 2000, "timestamp": "2025-06-29T12:03:45Z" }
Each operation — deposit, withdrawal, charge, refund — becomes an immutable event added to a log. The current state of the account is derived by replaying all events from the beginning.
This reconstruction process is called Hydration — the act of rebuilding the application state by processing and aggregating its associated events.
Hydration: Rebuilding State from History
Hydration is the heart of event sourcing.
Imagine you're asked, “What’s the current balance in Account #101?” The system doesn’t just fetch a number from a database. Instead, it performs:
Query all events for Account #101:
[ { "type": "DEPOSIT", "amount": 5000 }, { "type": "WITHDRAW", "amount": 1000 }, { "type": "DEPOSIT", "amount": 2000 } ]
Apply them in order:
Start with 0 + 5000 → 5000 - 1000 → 4000 + 2000 → 6000
Return final state: ₹6,000.
This process is purely functional — it doesn't mutate data; it computes state based on a sequence of decisions made over time.
With Event Sourcing, the event log is the database, and the state is just a cached view.
Benefits Unlocked: Replay, Recovery, and Audit Trail
Because the system stores a full event stream, it becomes trivially easy to:
Replay events to compute the state at any previous point in time.
Audit what happened, when, and why — including who initiated each event.
Debug errors by replaying scenarios under a test environment.
For instance, to understand how a user’s balance changed between June 1 and June 10, you can simply replay the subset of events in that window. This is invaluable for compliance, fraud detection, and root cause analysis.
Challenges of Reading Logs & the Need for Caching
One challenge in this model is that hydration requires reading and processing the entire event log — potentially thousands of events. This can be expensive in real-time systems.
To solve this, systems often use:
Snapshots: Periodic materialized state stored after N events (e.g., after 1000 events, store the current balance as a snapshot).
Caches: In-memory state that is updated as new events arrive.
Projections: Read-optimized views built by processing the event stream and storing the computed results for fast access.
This ensures that hydration only reprocesses a small number of events since the last snapshot — keeping the system fast and scalable.
Concurrency and Race Conditions Solved with Append-Only Logs
In a traditional system, two threads updating the same row can cause race conditions or even data loss. In contrast, event sourcing’s append-only nature removes this issue.
There are no destructive updates — only new events.
Each worker or service appends its event with a unique timestamp and sequence number, making concurrent processing both safe and reproducible.
Closing Thoughts
Event Sourcing fundamentally rethinks how systems manage state. Instead of overwriting the present, it preserves the past, empowering developers to build more robust, traceable, and fault-tolerant systems.
Yes, it comes with complexity: event versioning, log growth, hydration strategies, and partitioned processing. But for domains where data correctness, auditability, and scalability matter — it's a game-changer.
Thank you @Piyush Garg for his guidance on this topic. Youtube Video Link
Subscribe to my newsletter
Read articles from Arpit directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
