Event Sourcing Series Part 5: Key Concepts and Patterns
September 25, 2025 · 8 min read
DDD, Event Sourcing, Saga Pattern, System Design, Architecture, Interview Prep
This is Part 5 of a 5-part series on Event Sourcing and Saga Orchestration with Azure.
You've learned the concepts. You've seen the implementation. Now let's make sure you can articulate this knowledge in interviews and, more importantly, know when to recommend simpler alternatives.
How DDD, Event Sourcing, and Sagas Connect
These three concepts are often mentioned together but serve different purposes:
┌─────────────────────────────────────────────────────────────────┐
│ Domain-Driven Design (DDD) │
│ Strategic patterns for complex business domains │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Event Sourcing (Optional) │ │
│ │ Persistence strategy: store events, not state │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────┐ │ │
│ │ │ Saga Pattern (Optional) │ │ │
│ │ │ Coordinate transactions across aggregates │ │ │
│ │ └─────────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
DDD is the overarching approach - you can do DDD without event sourcing. Event Sourcing is one way to persist aggregates - you can do event sourcing without full DDD. Sagas coordinate multi-aggregate operations - you can use sagas with or without event sourcing.
Common Interview Questions
Q: "What is Event Sourcing?"
Good Answer: "Instead of storing current state, we store every event that happened to an entity. The current state is derived by replaying events. This gives us a complete audit trail, the ability to query historical state, and natural integration with event-driven architectures."
Great Answer (add context): "...but I'd only recommend it when you have genuine audit requirements or need temporal queries. For most CRUD applications, it adds significant complexity without proportional benefit. The schema evolution challenges and debugging complexity are real costs."
Q: "When would you use Event Sourcing?"
| Good Use Cases | Poor Use Cases |
|---|---|
| Financial transactions requiring audit | Simple CRUD applications |
| Healthcare records (compliance) | Content management systems |
| Legal document history | User profile management |
| Complex domain with rich events | E-commerce catalogs |
| Systems needing temporal queries | Most internal tools |
Q: "What's the difference between Choreography and Orchestration?"
Choreography: "Each service listens to events and decides what to do. No central coordinator. It's loosely coupled but hard to understand the full flow and debug issues."
Orchestration: "A central orchestrator tells each service what to do and when. Easier to understand, modify, and debug, but creates a dependency on the orchestrator."
When I prefer each: "For simple 2-3 step processes, choreography is fine. For anything more complex, I prefer orchestration because visibility into the saga state is crucial for operations."
Q: "How do you handle failures in a distributed transaction?"
Answer: "Traditional distributed transactions (2PC) don't work well in microservices - they're slow and fragile. Instead, I use the Saga pattern with compensating actions.
Each step has a corresponding compensation. If step 3 fails, I run compensations for steps 2 and 1 in reverse order. The key is that compensations must be idempotent since they might run multiple times.
For implementation, I'd use Azure Durable Functions which handles state persistence, retries, and timeouts automatically."
Q: "What is an Aggregate in DDD?"
Answer: "An aggregate is a cluster of domain objects treated as a single unit for data changes. It has:
- A root entity (the Aggregate Root)
- Internal entities and value objects
- A consistency boundary - changes within an aggregate are transactional
For example, an Order aggregate might contain OrderItems. You always load and save the entire Order, never individual items. This ensures invariants like 'order total must match sum of items' are always enforced."
Q: "How do you handle eventual consistency?"
Answer: "In event-driven systems, read models are often eventually consistent with writes. I handle this by:
- Designing the UI for it - Show 'processing' states, use optimistic updates
- Using appropriate read model stores - Redis or Cosmos for fast reads
- Setting expectations - Most users don't need immediate consistency
- Providing refresh mechanisms - Pull-to-refresh, websocket updates
The key insight is that most business processes are already eventually consistent - when you deposit a check, it doesn't clear instantly."
Q: "What's the Outbox Pattern?"
Answer: "It solves the dual-write problem: when you need to update a database AND publish a message, but they can't share a transaction.
Solution: Write the message to an outbox table in the same database transaction as the entity change. A background process reads the outbox and publishes messages. This guarantees that if the database commit succeeds, the message will eventually be published."
// Same transaction
await db.Orders.AddAsync(order);
await db.Outbox.AddAsync(new OutboxMessage { Event = orderCreatedEvent });
await db.SaveChangesAsync(); // Atomic!
// Background job publishes from outbox
Q: "What's the difference between an Entity and a Value Object?"
| Entity | Value Object |
|---|---|
| Has identity (ID) | No identity |
| Mutable over time | Immutable |
| Compared by ID | Compared by value |
| Example: Customer, Order | Example: Money, Address, DateRange |
// Entity - identity matters
var customer1 = new Customer(id: "123", name: "John");
var customer2 = new Customer(id: "123", name: "John Updated");
// customer1 == customer2 (same ID)
// Value Object - value matters
var money1 = new Money(100, "USD");
var money2 = new Money(100, "USD");
// money1 == money2 (same value)
Architecture Decision Questions
Q: "You're designing a new order management system. Walk me through your architecture decisions."
Framework for answering:
-
Clarify requirements
- "What's the scale? Hundreds of orders per day or millions?"
- "Are there audit/compliance requirements?"
- "How complex is the domain? Just CRUD or complex workflows?"
-
Start simple
- "For most order systems, I'd start with a straightforward architecture: API → Service Layer → Database. No event sourcing unless there's a specific need."
-
Add complexity only when justified
- "If we need complete audit trails, I'd consider event sourcing for the Order aggregate specifically."
- "If orders involve multiple services (payment, inventory, shipping), I'd use a saga orchestrator."
-
Be specific about trade-offs
- "Event sourcing gives us perfect audit but complicates debugging and schema evolution."
- "Sagas add operational complexity but give us reliable multi-service coordination."
Q: "The business says they might need audit trails in the future. Should we use event sourcing now?"
Answer: "I'd push back on that. 'Might need' isn't strong enough justification for the complexity cost.
Instead, I'd:
- Add basic audit columns (CreatedAt, UpdatedAt, ModifiedBy)
- Consider SQL Server temporal tables for point-in-time queries
- Ensure our domain events are well-defined (for future flexibility)
If requirements solidify, we can introduce event sourcing for specific aggregates. It's easier to migrate to event sourcing later than to remove it."
Red Flags to Watch For
In interviews (and in real projects), watch for these anti-patterns:
Over-Engineering Signals
- "We're using event sourcing for everything" - Why? Most domains don't need it.
- "We have 47 microservices" - For how many developers? Organizational complexity matters.
- "We're doing full DDD with all tactical patterns" - Is the domain actually that complex?
Under-Engineering Signals
- "We'll add distributed transactions later" - They don't work. Plan for sagas upfront.
- "Eventual consistency is fine everywhere" - Some operations need strong consistency.
- "We'll handle failures manually" - At scale, manual intervention doesn't work.
My Decision Checklist
When evaluating these patterns for a project:
Event Sourcing
□ Regulatory audit requirements exist
□ Temporal queries are a core feature
□ Team has event sourcing experience
□ We accept eventual consistency trade-offs
□ We have time to build proper tooling (replay, projections)
If < 3 checked → Don't use event sourcing
Saga Orchestration
□ Business process spans 3+ services
□ We need visibility into process state
□ Compensating actions are well-defined
□ Operations team can handle saga monitoring
□ We have budget for orchestration infrastructure
If < 3 checked → Consider choreography or monolith
Full DDD
□ Domain is genuinely complex (not just CRUD)
□ Domain experts are available and engaged
□ Team understands DDD tactical patterns
□ We have time for proper domain modeling
□ Business logic changes frequently
If < 3 checked → Use simpler patterns (service layer, anemic domain)
Closing Thoughts
The most senior thing you can do in an interview is recommend not using a complex pattern when it's not needed.
Interviewers want to see that you:
- Understand the patterns deeply
- Know when to apply them appropriately
- Can articulate trade-offs honestly
- Have practical experience with the challenges
Event sourcing, DDD, and sagas are powerful tools. Like all powerful tools, they can cause damage when misused. The best engineers I've worked with know when to reach for them - and when to keep things simple.
This concludes the 5-part series on Event Sourcing and Saga Orchestration:
- Part 1: The Honest Truth About Event Sourcing
- Part 2: Event Sourcing with Azure - Building Blocks
- Part 3: Saga Orchestration - Distributed Transactions Done Right
- Part 4: Implementing a Saga Orchestrator with Azure Durable Functions
- Part 5: Putting It All Together - Interview-Ready Knowledge (You are here)
Thanks for reading. If this helped you understand when (and when not) to use these patterns, it was worth writing.