Implement Event Sourcing pattern
✓Works with OpenClaudeYou are an architect implementing the Event Sourcing pattern. The user wants to build a system where all state changes are captured as immutable events and the current state is reconstructed by replaying those events.
What to check first
- Verify you have a persistent event store (PostgreSQL, EventStoreDB, or similar) ready to store immutable event records
- Check that your domain model is designed to emit domain events with a clear event schema (event type, aggregate ID, timestamp, payload)
- Confirm you understand the aggregate pattern — each aggregate has a unique ID and owns a stream of events
Steps
- Design your event schema with required fields:
aggregateId,eventType,timestamp,version,data, and optionallymetadata - Create an EventStore interface/class with methods:
append(event),getEvents(aggregateId), andgetAllEvents() - Implement event serialization/deserialization to JSON with proper type discriminators for each event subclass
- Build an EventSourcingRepository that reconstructs aggregate state by fetching all events and calling
applyEvent()for each one - Create event handler functions that update the aggregate's internal state based on event type
- Implement snapshots (optional but critical for performance): store aggregate snapshots every N events to avoid replaying thousands of events
- Add event versioning strategy to handle schema migrations when event structures change over time
- Set up event listeners/projections that consume events asynchronously to build read models or trigger side effects
Code
// Domain Event base class
abstract class DomainEvent {
constructor(
readonly aggregateId: string,
readonly timestamp: Date = new Date(),
readonly version: number = 1,
) {}
abstract getEventType(): string;
}
// Concrete domain events
class BankAccountCreated extends DomainEvent {
constructor(
aggregateId: string,
readonly accountHolder: string,
readonly initialBalance: number,
) {
super(aggregateId);
}
getEventType() {
return 'BankAccountCreated';
}
}
class MoneyDeposited extends DomainEvent {
constructor(aggregateId: string, readonly amount: number) {
super(aggregateId);
}
getEventType() {
return 'MoneyDeposited';
}
}
class MoneyWithdrawn extends DomainEvent {
constructor(aggregateId: string, readonly amount: number) {
super(aggregateId);
}
getEventType() {
return 'MoneyWithdrawn';
}
}
// Aggregate root
class BankAccount {
private balance: number = 0;
private accountHolder: string = '';
private version: number = 0;
private uncommittedEvents: DomainEvent[] = [];
static recreateFromHistory(events: DomainEvent[]): BankAccount {
const
Note: this example was truncated in the source. See the GitHub repo for the latest full version.
Common Pitfalls
- Treating this skill as a one-shot solution — most workflows need iteration and verification
- Skipping the verification steps — you don't know it worked until you measure
- Applying this skill without understanding the underlying problem — read the related docs first
When NOT to Use This Skill
- When a simpler manual approach would take less than 10 minutes
- On critical production systems without testing in staging first
- When you don't have permission or authorization to make these changes
How to Verify It Worked
- Run the verification steps documented above
- Compare the output against your expected baseline
- Check logs for any warnings or errors — silent failures are the worst kind
Production Considerations
- Test in staging before deploying to production
- Have a rollback plan — every change should be reversible
- Monitor the affected systems for at least 24 hours after the change
Related Architecture Skills
Other Claude Code skills in the same category — free to download.
Singleton Pattern
Implement Singleton pattern
Factory Pattern
Implement Factory pattern
Observer Pattern
Implement Observer/PubSub pattern
Strategy Pattern
Implement Strategy pattern
Repository Pattern
Implement Repository pattern for data access
Dependency Injection
Set up dependency injection
CQRS Setup
Implement CQRS pattern
Want a Architecture skill personalized to YOUR project?
This is a generic skill that works for everyone. Our AI can generate one tailored to your exact tech stack, naming conventions, folder structure, and coding patterns — with 3x more detail.