Event Sourcing Pattern in Java
Learn Event Sourcing Pattern in Java with Kafka, Event Store, Event Replay, CQRS integration, audit history, microservices architecture, banking examples, and interview questions.
What You Will Learn
- What is Event Sourcing?
- Why Event Sourcing is Needed
- Event Store Architecture
- Event Replay
- Snapshot Pattern
- CQRS + Event Sourcing
- Kafka Integration
- Banking Examples
- Enterprise Use Cases
- Benefits and Limitations
- Interview Questions
Introduction
Traditional applications store only the latest state.
Example Bank Account:
Account Balance = $10,000
Database stores:
ACCOUNT
--------------------------------
ID BALANCE
1 10000
Question:
How did balance become $10,000?
What transactions occurred?
Can we reconstruct history?
Traditional systems often cannot answer easily.
Event Sourcing solves this problem.
What is Event Sourcing?
Event Sourcing is an architectural pattern where every state change is stored as an immutable event.
Instead of storing:
Current State
Store:
History Of Events
Purpose of Event Sourcing
Primary Goal:
Store Every Change
As An Immutable Event
Traditional Database Approach
flowchart LR
A[Application]
B[Update Account Balance]
C[Database]
A --> B
B --> C
Only latest value exists.
Event Sourcing Approach
flowchart LR
A[Application]
B[Event Store]
A --> B
Store every business event.
Traditional Example
Bank Account:
Balance = 10000
We only know:
Current State
We do NOT know:
Deposit History
Withdraw History
Transfer History
Event Sourcing Example
Store events:
Account Created
Deposit 5000
Deposit 3000
Withdraw 1000
Deposit 3000
Current Balance:
10000
calculated from events.
Core Idea
flowchart LR
A[Command]
B[Generate Event]
C[Store Event]
D[Build Current State]
A --> B
B --> C
C --> D
What is an Event?
An event represents:
Something That Already Happened
Examples:
AccountCreated
MoneyDeposited
MoneyWithdrawn
OrderPlaced
ClaimApproved
Events are:
Immutable
Never modified.
Event Characteristics
Past Tense
Immutable
Business Meaningful
Time Ordered
Bank Account Example
Event 1:
{
"event":"AccountCreated",
"accountId":"123"
}
Event 2
{
"event":"MoneyDeposited",
"amount":5000
}
Event 3
{
"event":"MoneyWithdrawn",
"amount":1000
}
Event Store
Instead of:
ACCOUNT
Store:
EVENT_STORE
Event Store Structure
EventId
AggregateId
EventType
Payload
Timestamp
Event Store Architecture
flowchart LR
A[Commands]
B[Event Store]
C[Events]
A --> B
B --> C
Account Lifecycle
flowchart LR
A[Account Created]
B[Deposit 5000]
C[Deposit 3000]
D[Withdraw 1000]
E[Current Balance]
A --> B
B --> C
C --> D
D --> E
Event Replay
One of the biggest advantages.
Current state can be rebuilt by replaying events.
Replay Flow
flowchart LR
A[Event 1]
B[Event 2]
C[Event 3]
D[Rebuild State]
A --> D
B --> D
C --> D
Replay Example
Events:
Deposit 5000
Deposit 3000
Withdraw 1000
Replay:
0 + 5000
5000 + 3000
8000 - 1000
Result:
7000
Aggregate
Aggregate is the business entity.
Example:
Account
Order
Claim
Policy
Events belong to aggregates.
Aggregate Flow
flowchart LR
A[Account Aggregate]
B[Account Events]
A --> B
Snapshot Pattern
Problem:
Millions Of Events
Replay becomes slow.
Solution:
Snapshot
Store periodic state.
Snapshot Example
Event 1
Event 2
Event 3
Snapshot
Event 4
Event 5
Replay starts from snapshot.
Snapshot Architecture
flowchart LR
A[Events]
B[Snapshot]
C[Latest Events]
D[Current State]
A --> B
B --> D
C --> D
CQRS + Event Sourcing
Most common architecture.
Commands:
Generate Events
Queries:
Read Projections
CQRS + Event Sourcing Flow
flowchart LR
A[Command]
B[Event Store]
C[Projector]
D[Read Database]
E[Query]
A --> B
B --> C
C --> D
D --> E
Projection
Projection creates read models from events.
Example:
Order Events
↓
Customer Summary
↓
Dashboard
Projection Flow
flowchart LR
A[Events]
B[Projection]
C[Read Model]
A --> B
B --> C
Kafka Integration
Kafka works naturally with Event Sourcing.
Events become messages.
Kafka Architecture
flowchart LR
A[Command Service]
B[Event Store]
C[Kafka Topic]
D[Consumers]
A --> B
B --> C
C --> D
Spring Event Example
Event:
public record MoneyDepositedEvent(
String accountId,
Double amount) {
}
Event Handler
@Service
public class AccountProjection {
public void handle(
MoneyDepositedEvent event) {
// Update Read Model
}
}
Banking Example
Events:
AccountCreated
MoneyDeposited
MoneyWithdrawn
MoneyTransferred
Audit history becomes automatic.
Banking Architecture
flowchart LR
A[Transfer Command]
B[Event Store]
C[Account Events]
D[Read Database]
A --> B
B --> C
C --> D
Insurance Example
Events:
ClaimSubmitted
ClaimReviewed
ClaimApproved
ClaimPaid
Every step preserved forever.
Insurance Workflow
flowchart LR
A[Claim Submitted]
B[Claim Reviewed]
C[Claim Approved]
D[Claim Paid]
A --> B
B --> C
C --> D
Order Processing Example
Events:
OrderPlaced
PaymentCompleted
InventoryReserved
OrderShipped
OrderDelivered
Order Lifecycle
flowchart LR
A[Order Placed]
B[Payment Completed]
C[Inventory Reserved]
D[Shipped]
E[Delivered]
A --> B
B --> C
C --> D
D --> E
Event Sourcing Benefits
Complete Audit History
Every Change Recorded
Event Replay
Rebuild Entire System
Time Travel
View System State
At Any Point In Time
CQRS Friendly
Perfect Integration
Event Driven Architecture
Natural Fit
Limitations
❌ Complex Design
❌ Event Versioning
❌ Eventual Consistency
❌ More Storage Required
❌ Harder Debugging
Event Versioning Problem
Old Event:
{
"customer":"Venu"
}
New Event:
{
"customer":"Venu",
"email":"[email protected]"
}
Need backward compatibility.
Event Sourcing vs Traditional CRUD
| Feature | CRUD | Event Sourcing |
|---|---|---|
| Current State | Yes | Derived |
| History | Limited | Complete |
| Audit Trail | Manual | Automatic |
| Replay | No | Yes |
| Complexity | Low | High |
Event Sourcing vs CQRS
| Feature | CQRS | Event Sourcing |
|---|---|---|
| Read/Write Separation | Yes | Optional |
| Stores Events | No | Yes |
| Often Together | Yes | Yes |
Enterprise Use Cases
Banking
Transactions
Account History
Audit Trails
Insurance
Claims
Policy Lifecycle
Compliance Tracking
Retail
Order History
Inventory Events
Trading Platforms
Trade Events
Portfolio Tracking
Healthcare
Patient History
Medical Records
Real Enterprise Architecture
flowchart LR
A[Client]
B[API Gateway]
C[Command Service]
D[Event Store]
E[Kafka]
F[Projection Service]
G[Read Database]
A --> B
B --> C
C --> D
D --> E
E --> F
F --> G
When To Use Event Sourcing
Use when:
Audit History Required
Complex Business Workflows
Banking Systems
Insurance Systems
Trading Platforms
Event Driven Architecture
When NOT To Use Event Sourcing
Avoid when:
Simple CRUD Applications
Small Systems
Low Audit Requirements
Interview Questions
What is Event Sourcing?
Store every state change as an immutable event.
What is Event Store?
Database that stores business events.
What is Event Replay?
Rebuilding state by replaying events.
Why Use Snapshots?
Improve replay performance.
CQRS Relationship?
CQRS often uses Event Sourcing.
Kafka Relationship?
Kafka commonly transports events.
Biggest Benefit?
Complete audit history.
Biggest Drawback?
Complexity.
Key Takeaways
- Event Sourcing stores events instead of current state.
- Every state change becomes an immutable event.
- Supports audit trails, replay, and time travel.
- Frequently combined with CQRS.
- Kafka integrates naturally with Event Sourcing.
- Widely used in Banking, Insurance, Trading, and Enterprise Systems.
- One of the most advanced architecture patterns in modern distributed systems.