Event Sourcing
Concurrent Programming
Conflict Resolution
Software Development
Data Management

Event Sourcing concurrently creating conflicting events

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Event Sourcing is a design pattern in software engineering where state changes are logged as a sequence of events. Each event represents a change in the system rather than just the final state. This model allows for high traceability, replaying of events to recover state, and complex business processes that handle diverse state changes over time.

The Challenge of Concurrent Conflicting Events

A significant challenge in event-sourced systems arises when concurrent operations lead to conflicting events. This can occur in distributed systems where multiple clients or services modify the same piece of data simultaneously without awareness of each other's operations.

Example of Concurrently Conflicting Events

Imagine a simple event sourcing system for an online inventory management. Two users access the system at the same time to update the stock for the same item:

  • User A sets the stock of Item X to 30.
  • User B sets the stock of Item X to 25.

Both updates are based on the stock level seen by each user when they queried the system, but because these updates happen concurrently, without proper handling, one update might overwrite the other unintentionally.

Handling Concurrent Conflicts

1. Last Write Wins (LWW)

One simplistic approach is the Last Write Wins strategy where the system saves the last write operation executed. However, this could lead to significant data loss as one user's changes are completely discarded.

StrategyDescriptionProsCons
Last Write Wins (LWW) The last completed write operation overwrites others. Simple to implement High risk of data loss

2. Versioning and Optimistic Concurrency Control

A more refined approach involves adding a version number to each record. When an update is made, the version is checked:

  • If the current version matches the expected version from the client, the update proceeds and the version increments.
  • If the versions conflict (the server version is higher than the client's), it indicates that another concurrent update has occurred. The client can then decide to retry the transaction or handle the conflict differently.

3. Event Merging

Another technique involves merging events where possible. This requires domain-specific logic to understand when and how events can be combined.

  • In our example, instead of overwriting, the system can merge two stock set events by perhaps averaging, or reporting the conflict to an admin.

4. Domain-Driven Resolutions

Some conflicts need business intelligence to resolve appropriately. This might involve domain-driven logic that decides based on business rules which event should take priority, or how events should be combined.

Implementation Example: Event Merging

Using pseudo-code, let's demonstrate how an event merging strategy might be implemented:

python
1class InventoryEvent:
2    def __init__(self, item_id, new_stock_level, timestamp):
3        self.item_id = item_id
4        self.new_stock_level = new_stock_level
5        self.timestamp = timestamp
6
7def merge_events(event1, event2):
8    if event1.item_id != event2.item_id:
9        raise ValueError("Cannot merge events for different items")
10    # Simple merge logic: choose the latest event
11    if event1.timestamp > event2.timestamp:
12        return event1
13    else:
14        return event2
15
16# Events received concurrently.
17event_a = InventoryEvent('X', 30, 1597902980)
18event_b = InventoryEvent('X', 25, 1597902990)
19
20# Resolve conflict
21resolved_event = merge_events(event_a, event_b)
22print(f'Resolved stock level: {resolved_event.new_stock_level}')

Conclusion

When employing Event Sourcing in systems where concurrency is a factor, special considerations must be made to handle conflicts effectively. Techniques like LWW, versioning, event merging, and domain-driven resolutions are critical in maintaining integrity and consistency in data. Each approach has its pros and cons, and the choice of strategy often depends on specific use case requirements and domain complexities.


Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.