Marcio Cunha

Microservices in conflict? How to design Event Sourcing

Learn how to store application state in microservices as an immutable sequence of events for absolute auditability and high resilience.

Marcio Cunha•3 min
Also available in:PortuguêsEspañol
Summary
  • Event-driven storage replaces traditional data overwriting with an immutable historical log.
  • Distributed system auditing becomes native when every transaction turns into an indisputable fact.
  • Operational resilience increases dramatically by allowing state reconstruction at any given moment.
  • Sequential event storage requires rigorous planning around eventual consistency and data models.
  • Replaying historical logs simplifies complex debugging scenarios in modern microservices architectures.

The challenge of maintaining order in distributed systems

When breaking down a large system into independent microservices, the biggest hurdle is usually keeping track of information states. If two parts of an application try to update the same piece of data simultaneously across separate databases, inconsistencies occur and business logic breaks. In practice, this means customers might see incorrect balances or duplicate orders. To resolve this friction, engineers rely on architectures built upon historical facts, ensuring that no information is ever silently lost or overwritten.

What Event Sourcing is and how it works in practice

Event Sourcing fundamentally changes how we save data. Instead of storing only the current state of a record — such as a bank balance of one hundred dollars —, the system records every single change as an isolated, immutable event that can never be deleted or modified. Think of it like a bank account statement: you look not just at the final amount, but at every deposit and withdrawal that happened over time. When we need to know the current state, the system simply reads all events in order and calculates the final result from scratch.

Why immutability brings resilience and flawless auditing

In modern corporate environments, strict auditing is not just a luxury, but a legal and operational requirement. When using traditional tables that undergo constant updates, old data disappears forever, hindering investigations into failures or fraud. With immutable events, we get a perfect, native audit trail where every action has an exact timestamp and origin. This aligns closely with complex consistency strategies, such as those we explore when discussing transactional consistency using the Saga pattern, allowing failures to be isolated and corrected without corrupting the core database.

Operational challenges and the need for snapshots

Although calculating the current state by summing all past events is conceptually elegant, this approach introduces an obvious performance bottleneck. If an account has ten years of history with millions of small transactions, re-reading everything from the beginning on every query will make the application extremely slow. To solve this problem in practice, we use a technique called snapshots, which consists of taking a frozen picture of the current state at specific event intervals. Thus, the system reads only the latest saved snapshot and applies solely the events generated from that exact point onward.

How to handle schema evolution and changing business rules

Keeping immutable events forever creates an interesting challenge when business rules change over the years. If the structure of an event created in twenty-twenty differs from the structure required today, historical reading might break during state reconstruction. The solution requires careful event versioning and the use of translators or adapters in code that can interpret older formats and convert them to the current standard transparently. This care ensures that data longevity is not compromised by constant technological updates in the infrastructure. To complement this implementation in production environments, see our related technical analyses on How to optimize real-time AI inference with vLLM and Node.js freezing under high load? Use Worker Threads.

Final thoughts on adopting event-driven architectures

Adopting storage based on immutable sequences requires a profound mindset shift across the entire engineering and development team. It is not just about swapping a database tool, but about accepting that a system's past is more valuable than its momentary state. When well-designed, this model eliminates obscure conflicts between microservices, provides absolute traceability, and ensures the application continues operating with extreme resilience even in the face of catastrophic infrastructure failures.