Blog
Mert Özen's blog posts on software development, backend, frontend, and DevOps.
The Hard Parts of Event Sourcing: GDPR, Unique Constraints, and Dynamic Consistency Boundaries
Keep personal data out of events and encrypt it with crypto-shredding when it must stay; protect cross-stream uniqueness with a natural-key stream id or an Inline projection with a unique index, and rules spanning two aggregates with a Dynamic Consistency Boundary. AES-GCM crypto-shredding with Marten 9, a race between two concurrent registrations, a campaign quota with DcbConcurrencyException, and not calling external services on replay.
Event Versioning and Snapshots: Changing Event Schemas Without Breaking History
Written events are not changed; new code reads old shapes through tolerant deserialization, fixed JSON names, and upcasters, while snapshots are turned on based on measurement and together with a rebuild. A property rename that silently turns into zero, RespectRequiredConstructorParameters, a Marten upcaster, a Turkish-culture alias breaking on a namespace move, the cost of in-place migration, a snapshot serialization trap, and closing the books.
Projections: Building Read Models with Inline, Async, and Live Projections
A projection is a function that turns events into a read model shaped by a specific question; Inline runs in the same transaction as the events, Async runs in the background with the daemon, and Live is never stored. A stock badge, a monthly stock movement report, and reservations waiting to ship from the Bookstore stock ledger; checkpoints, changing a projection and rebuilding it, dead letters, and a failed rebuild emptying a read model.
Working with an Event Store: Append, Optimistic Concurrency, and Streams with Marten and PostgreSQL
An event store's core contract is appending to a stream only while it is at the expected version; Marten provides this on PostgreSQL with a unique index on (stream_id, version) and FetchForWriting. Setting up Marten 9, StartStream/Append, wiring a decider to FetchForWriting, a race between two writers, stream id strategies, KurrentDB versus your own table, and event names that break under a Turkish culture.