Skip to content

Event Sourcing vs CRUD

1. Decision

Choose traditional CRUD for standard operational domain applications where only the current state of an entity matters; choose Event Sourcing for audit-critical domains (banking ledgers, insurance claims, order fulfillment, healthcare) where every historical state change must be preserved as an immutable append-only event sequence.


2. 30-Second Answer

In traditional CRUD, database tables store only the current state of an entity. When an address is updated, the old address is overwritten via UPDATE, destroying historical state context. In Event Sourcing, system state is never updated or overwritten. Instead, all state mutations are persisted as an append-only, ordered sequence of immutable domain events (OrderCreated, ItemAdded, PaymentProcessed, OrderShipped) stored in an Event Store. The current state of an entity is derived dynamically by replaying its historical event stream from time zero. Event Sourcing provides complete audit trails, time-travel debugging, and historical event replayability, but introduces complex event schema versioning and requires CQRS projections for read queries.


3. Decision Matrix

Option Best For Avoid When Latency Scalability Consistency Operational Complexity
CRUD (Current State Persistence) Standard CRUD applications, e-commerce catalogs, simple administrative backends, early-stage MVPs Regulatory compliance requiring full state change auditability, time-travel analytics Low for point reads/writes (\(O(1)\) row lookup) Scale-up; Read Replicas; Sharding Immediate ACID (Single database instance) Low
Event Sourcing (Append-Only Event Store) Financial ledgers, banking double-entry bookkeeping, insurance claim tracking, flight reservations, supply chain audit logs Simple CRUD applications where historical state changes hold zero business value Sub-millisecond append write; Read requires Snapshots or CQRS Projections High Write throughput (Append-only disk writes); Bounded by event stream length Strong per Event Stream (Append-only ordering); Eventual for Read Projections High (Snapshots, Event Schema Versioning, CQRS projections)

4. Selection Rules

Requirement Best Choice Rationale / Example
Financial Ledger / Double-Entry Bookkeeping Event Sourcing Bank accounts store credit/debit transaction event logs, never static balance values
Complete Auditability & Regulatory Compliance Event Sourcing Medical or insurance system requires proving who changed what state at exact timestamps
Time-Travel Debugging & State Replay Event Sourcing Reconstruct exact system state as it existed on last Tuesday at 14:00:00
Standard E-Commerce Product Catalog CRUD Updating product title/price overwrites previous state cleanly without event overhead
Retroactive Business Feature Analytics Event Sourcing Train ML model over 3 years of raw historical user interaction events

5. Tradeoffs

  1. Immutable Audit History vs Storage Accumulation
  2. Gain (Event Sourcing): Complete, un-alterable historical audit record; zero loss of domain context.
  3. Lose (Event Sourcing): Event log grows infinitely; requires disk retention policies and Snapshots.
  4. Append-Only Write Speed vs Read State Derivation Latency
  5. Gain (Event Sourcing): Writes execute as ultra-fast \(O(1)\) append-only log entries.
  6. Lose (Event Sourcing): Replaying 100,000 events to compute current state is slow (requires Snapshots).
  7. Time-Travel Replayability vs Event Schema Evolution
  8. Gain (Event Sourcing): Replay historical events into new analytics databases at any time.
  9. Lose (Event Sourcing): Modifying event schemas over multi-year logs requires complex upcasters/versioning.
  10. Natural Pairing with CQRS vs Increased Architectural Moving Parts
  11. Gain: Event Store acts as Command Model; Projections generate custom Read Models cleanly.
  12. Lose: Must operate Event Stores (EventStoreDB / Kafka), CDC pipelines, and Read databases simultaneously.
  13. GDPR "Right to be Forgotten" Compliance
  14. Gain (CRUD): Execute DELETE FROM users WHERE id = X to erase user data instantly.
  15. Lose (Event Sourcing): Immutable append-only logs cannot delete historical events (requires Crypto-Tredding).

6. Interview Counter Questions

  1. How do Snapshots optimize state calculation in Event Sourcing when an event stream contains 100,000 events?
  2. How do you handle GDPR "Right to be Forgotten" (data deletion) in an immutable append-only Event Store?
  3. What is Event Upcasting and how do you handle Event Schema Versioning over multi-year event streams?
  4. What is the difference between an Event, a Command, and a Read Model Projection?
  5. How do you guarantee concurrency control when two users attempt to append to the same Event Stream simultaneously?
  6. Why does Event Sourcing almost always require CQRS (Command Query Responsibility Segregation)?
  7. How does EventStoreDB or PostgreSQL handle Event Sourcing storage under the hood?
  8. What is Crypto-Trashing / Crypto-Tredding for deleting data in immutable logs?
  9. When is Event Sourcing considered an architectural anti-pattern?
  10. How do you debug an issue in an Event Sourcing application?

7. Gold Standard Answers

  1. Snapshots: Periodically (e.g. every 100 events) save a cached copy of the current state (AggregateSnapshot). To load current state, fetch the latest Snapshot and replay only events published after the snapshot timestamp.
  2. Use Crypto-Tredding: Encrypt PII inside events with a user-specific encryption key. When user requests deletion, destroy the user's encryption key. The immutable events remain, but PII payload becomes permanently un-decryptable garbage.
  3. Upcasters: Middleware functions that intercept legacy event versions during event log replaying and transform V1 event JSON structures into V2/V3 schemas in-memory before passing to application aggregates.
  4. Command: Intent to change state (CreateOrder - can be rejected). Event: Fact that state changed (OrderCreated - immutable). Projection: Read-optimized view computed from events.
  5. Use Optimistic Concurrency Control (OCC): Store expected_version on the stream. When appending OrderCreated, client sends version 5. If database stream version is currently 6, the append is rejected.
  6. Event Stores are optimized for append-only writes by Stream ID, but terrible for arbitrary queries (SELECT * WHERE city = 'NY'). CQRS projections consume events and build read-optimized databases for queries.
  7. Dedicated Event Store (EventStoreDB) uses append-only segment files indexed by Stream ID. Relational DBs (Postgres) use an append-only events table (stream_id, version, event_type, payload_json) with a UNIQUE constraint on (stream_id, version).
  8. Crypto-Trashing generates a unique encryption key per user stored in a Key Management Service (KMS). Deleting the key from KMS renders all PII in immutable append-only logs un-readable instantly.
  9. Anti-pattern for: simple CRUD applications, short-lived ephemeral domain state, teams lacking distributed systems expertise, or domains where historical audit logs hold zero business value.
  10. Replay the exact historical event stream in a local development environment. Because event streams are deterministic, replaying events reproduces the exact production bug state consistently.

8. Common Mistakes

  • Using UPDATE or DELETE SQL statements inside an Event Sourcing Event Store database.
  • Attempting to query an Event Store directly for complex UI screens without building CQRS Read Projections.
  • Forgetting to implement Snapshots, causing aggregate load times to degrade as event streams grow to thousands of events.
  • Mutating historical event payloads on disk when schemas change instead of using Event Upcasters.
  • Over-engineering simple CRUD domain entities (e.g., user preference toggles) with Event Sourcing.

9. Keywords

Event Sourcing, Traditional CRUD, Immutable Event Log, Event Store, Aggregate, Snapshots, Event Upcasting, Schema Versioning, Crypto-Tredding, Optimistic Concurrency Control (OCC), Projections, CQRS, Time-Travel Debugging, EventStoreDB.


10. Cheat Sheet

  • Core Difference: CRUD = Stores current state (overwrites history); Event Sourcing = Stores sequence of immutable events (state derived by replay).
  • Auditability: Event Sourcing provides 100% complete historical audit history out-of-the-box (OrderCreated, PaymentFailed, OrderShipped).
  • Performance Fix: Use Snapshots (save current state every 100 events) so state recovery replays only recent events.
  • GDPR Deletion: Use Crypto-Tredding (encrypt PII per user; destroy user's encryption key to erase data from immutable log).
  • Concurrency: Enforce Optimistic Concurrency Control (stream_id + expected_version) to prevent concurrent write collisions.
  • Schema Evolution: Use Upcasters (in-memory event transformers) to upgrade legacy V1 event schemas to V2 during replay.

11. Related Decisions