m@ksim.pro
Back to all posts
IT 3 min read

Event sourcing: build the audit trail before the features

Why event sourcing is not an architecture fashion but a practical answer to the question of what happened in your system yesterday.

Every few months a team comes to me with a version of the same problem. Something went wrong in the system - a balance was miscalculated, an order disappeared, a status flipped to a wrong value. They need to know what happened. And they cannot find out, because the database only stores the current state.

This is not a logging problem. It is an architecture problem that was made invisible by the way most systems are built by default.

What event sourcing actually is

The idea is simple. Instead of overwriting a record when something changes, you append an event that describes what happened. The current state is derived by replaying those events.

The account balance is not a number in a column. It is the result of all deposits, withdrawals, and adjustments since the account was opened. The order status is not a field. It is the last in a chain of events: created, confirmed, shipped, delivered.

This sounds like extra work, and it is - at first. But it shifts the question from "what is the state now?" to "what happened, and why?"

The audit trail problem

In regulated industries this is not optional. Banks, insurance companies, healthcare systems, logistics - they all have versions of the same requirement: show me the full history of this entity. Who changed it, when, with what values, from what trigger.

In a traditional mutable-state database, you reconstruct this from logs, backup snapshots, and memory. It is slow, incomplete, and always disputed.

With event sourcing the history is the data. There is nothing to reconstruct. You read the event stream.

When it is not the right tool

Event sourcing adds real complexity. The read path requires projection - you need to build and maintain views of the current state, which means additional storage and synchronisation logic. Schema evolution is harder: old events have to be understood by new code. Debugging a projection bug requires replaying history.

For a simple CRUD application with low regulatory pressure, this is overhead with little payback. I would not recommend it as a default.

The signal that event sourcing starts to pay off: when the team keeps building workarounds to answer "what happened?", or when audit requirements show up after the fact and the data is not there.

The practical path

You do not have to go all-in from day one. A reasonable middle position is to add an event log alongside a traditional state store - an append-only table or a stream where every meaningful mutation is recorded. This is not pure event sourcing, but it solves the audit problem without restructuring the whole data model.

If that pattern survives six months of production, you have a much better sense of whether the full event-sourcing architecture is worth the investment for your specific system.

One thing I always ask first

Before recommending event sourcing to anyone, I ask: what is the question you cannot answer today about your own system? If the answer is "I do not know what changed or why", event sourcing is worth considering seriously. If the answer is "our reads are too slow", it is probably the wrong medicine.

Architecture choices should be driven by the problems you actually have, not by what is interesting to build.

Back to all posts
Contact

If this resonated, write to me. I reply personally.

WhatsApp