Event sourcing pattern in Kafka - Time & Space Complexity
When using event sourcing with Kafka, we want to understand how the time to process events grows as more events happen.
We ask: How does the number of events affect the work Kafka does to rebuild state?
Analyze the time complexity of the following Kafka event sourcing snippet.
// Consume events from a Kafka topic
consumer.subscribe(['user-events'])
while (true) {
const records = consumer.poll(1000)
for (const record of records) {
// Apply event to rebuild user state
userState.apply(record.value)
}
}
This code reads events from Kafka and applies each event to update the user state.
Look for repeated work in the code.
- Primary operation: Loop over all events received from Kafka.
- How many times: Once per event in the topic, continuously as new events arrive.
As the number of events grows, the time to process all events grows too.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 event applications |
| 100 | 100 event applications |
| 1000 | 1000 event applications |
Pattern observation: The work grows directly with the number of events.
Time Complexity: O(n)
This means the time to rebuild or update state grows linearly with the number of events.
[X] Wrong: "Processing events is always constant time no matter how many events there are."
[OK] Correct: Each event must be applied, so more events mean more work, not the same amount.
Understanding how event processing time grows helps you explain system behavior clearly and shows you can reason about real-world data flow.
"What if we stored snapshots periodically to avoid replaying all events? How would that change the time complexity?"
Practice
Solution
Step 1: Understand event sourcing concept
Event sourcing means saving every change as a separate event instead of just the current state.Step 2: Relate to Kafka usage
Kafka topics store these events so consumers can read the full history and rebuild state if needed.Final Answer:
To save every change as an event for a full history -> Option AQuick Check:
Event sourcing = full history saved as events [OK]
- Thinking event sourcing deletes old data
- Believing it only keeps latest state
- Assuming events go to only one consumer
Solution
Step 1: Identify Kafka components roles
Kafka Producer sends data, Consumer reads data, Broker manages servers, Topic stores data.Step 2: Match storage role
Events are stored in Kafka Topics, which keep the event log for consumers.Final Answer:
Kafka Topic -> Option AQuick Check:
Events stored in Kafka Topic [OK]
- Confusing producer with storage
- Thinking consumer stores events
- Mixing broker with event storage
events = [
{"type": "create", "id": 1, "value": 10},
{"type": "update", "id": 1, "value": 20},
{"type": "create", "id": 2, "value": 5},
{"type": "delete", "id": 1}
]
state = {}
for event in events:
if event["type"] == "create" or event["type"] == "update":
state[event["id"]] = event["value"]
elif event["type"] == "delete":
state.pop(event["id"], None)
print(state)Solution
Step 1: Process each event in order
First create id 1 with value 10, then update id 1 to 20, create id 2 with 5, then delete id 1.Step 2: Determine final state
After deletion, id 1 is removed, only id 2 with value 5 remains.Final Answer:
{"2": 5} -> Option DQuick Check:
Delete removes id 1, only id 2 left [OK]
- Forgetting the delete event removes id 1
- Confusing update with create
- Assuming old values remain after update
state = {}
for event in events:
if event["type"] == "create":
state[event["id"]] = event["value"]
elif event["type"] == "update":
if event["id"] in state:
state[event["id"]] = event["value"]
elif event["type"] == "delete":
del state[event["id"]]
Solution
Step 1: Analyze delete operation
Using del without checking if the key exists can cause a KeyError if id is missing.Step 2: Check other conditions
Update correctly checks if id exists before updating; create overwrites which is allowed; else clause is optional.Final Answer:
Using del without checking if id exists causes KeyError -> Option BQuick Check:
del without check = KeyError risk [OK]
- Ignoring KeyError on delete
- Thinking update must create new id
- Believing create cannot overwrite
Solution
Step 1: Understand rebuilding state from events
Replaying all events from the start is slow for large data; deleting events loses history.Step 2: Use snapshots to optimize
Snapshots save a recent state, so only new events after snapshot need replay, improving efficiency.Final Answer:
Use snapshots periodically and then replay only recent events -> Option CQuick Check:
Snapshots + replay recent events = efficient rebuild [OK]
- Replaying all events every time (slow)
- Deleting events loses full history
- Reading only latest event misses changes
Ready to prove it?
Pass the test and this pattern moves unknown
