Event Sourcing & CQRS
Traditional databases store the current state of an entity. If you update a user’s address, the old address is overwritten and lost forever.
Event Sourcing is a different approach: you store every change that has ever happened as an immutable sequence of events. Redis Streams is the perfect engine for this.
1. The Pattern
Instead of UPDATE users SET address='...', you append an event: XADD user_events * type "AddressUpdated" new_address "...".
- Audit Trail: You have a perfect history of everything that happened.
- Time Travel: You can rebuild the state of the system at any point in time by replaying events up to that timestamp.
- Debuggability: If a bug corrupts your data, you can fix the code and replay the event log to correct the database.
2. CQRS (Command Query Responsibility Segregation)
Event Sourcing often pairs with CQRS.
- Write Side (Command): App writes events to the Redis Stream. This is fast and simple.
- Read Side (Query): Workers consume the stream and update “Read Models” (e.g., Redis Hashes, SQL tables, Search Indexes) optimized for queries.
3. Interactive: Event Replay
Observe how the “Current State” is just a derivation of the “Event Log”. Try replaying the events to rebuild the user’s profile.
Event Log (Source of Truth)
Current State (Derived)
{}
4. Code Examples: State Rebuilder
package main
import (
"context"
"fmt"
"github.com/redis/go-redis/v9"
)
func main() {
ctx := context.Background()
rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379"})
// Read all history
streams, _ := rdb.XRead(ctx, &redis.XReadArgs{
Streams: []string{"user_events", "0"},
Count: 1000,
Block: 0,
}).Result()
userState := make(map[string]string)
for _, stream := range streams {
for _, event := range stream.Messages {
values := event.Values
eventType := values["type"].(string)
// Reducer Logic
if eventType == "UserCreated" {
userState["id"] = values["id"].(string)
userState["name"] = values["name"].(string)
} else if eventType == "EmailUpdated" {
userState["email"] = values["email"].(string)
}
}
}
fmt.Println("Rebuilt State:", userState)
}
5. Summary
By combining Redis Streams with Event Sourcing, you gain a powerful architecture where your data is durable, auditable, and replayable. You are no longer just storing the “now”—you are storing the entire history of your business.