← Back to lessons|architecture
Passkeys not supported in this browser
Event Sourcing over CRUD for Financial Transaction Audit Trails
Team decided to replace standard PostgreSQL CRUD with Event Sourcing backed by Kafka to satisfy compliance audit requirements. An immutable event log preserves full transaction history including business context and user intent, with a materialized PostgreSQL view for read performance.
lesson_learnedevent-sourcingaudit-trailcompliancekafkapostgresqlfinancial-transactions
Created 6/21/2026, 3:34:40 PM
Content
DECISION: Migrate from standard CRUD in PostgreSQL to Event Sourcing with Kafka for financial transaction audit trails. CONTEXT: The team currently uses standard CRUD operations in PostgreSQL to manage financial transactions. The problem surfaced when compliance requested the audit history for transaction #8821 — specifically who changed the status from "pending" to "approved". Because PostgreSQL CRUD overwrites previous states on UPDATE, the full change history was unavailable. ALTERNATIVES CONSIDERED: 1. Database triggers writing to a history_logs table — REJECTED because triggers only see row-level changes (e.g., status changed from 1 to 2) and lack business context. They cannot capture WHY a change happened or the user intent behind it. DECISION RATIONALE: Event Sourcing stores a sequence of immutable domain events (e.g., TransactionCreated, TransactionApproved, StatusUpdated) instead of mutable state. This preserves the full audit trail including the "why" behind each change. The architecture uses Kafka as the immutable event log and a materialized view in PostgreSQL for fast read queries on the frontend. ARCHITECTURE: - Kafka: Immutable event log (append-only stream of domain events) - PostgreSQL: Materialized view for fast reads / frontend queries - Event producers: src/services/transactionService.ts - Event consumer/store: src/events/eventStore.ts REFERENCE: Martin Fowler's "Event Sourcing Pattern" article — industry standard reference that informed this decision. FILES INVOLVED: - src/services/transactionService.ts (event producers) - src/events/eventStore.ts (consumer/store logic)