Mert Özen Further With Every Line

Blog

Mert Özen's blog posts on software development, backend, frontend, and DevOps.

Series
10 posts found
What Is CQRS? From CQS to Command Query Responsibility Segregation
Software Architecture PART 01

What Is CQRS? From CQS to Command Query Responsibility Segregation

CQRS splits one model into two, one for writing (commands) and one for reading (queries); Greg Young took Meyer's method-level CQS principle up to the model level. We show with a real compiler error and a load count why an aggregate does not fit a list screen, then cover the three levels of CQRS, how it differs from Event Sourcing and MediatR, and Fowler's 'only where it pays off' warning.

7 Nov 2026 12 min 5
CQRS in a Single Database: Aggregates on the Write Side, Projections on the Read Side
Software Architecture PART 02

CQRS in a Single Database: Aggregates on the Write Side, Projections on the Read Side

CQRS in a single database means saving the aggregate through EF Core's change tracker on the write side and projecting from the same tables on the read side without ever touching the aggregate. What PlaceOrder and CancelOrder should return, a separate flat read DbContext, Dapper over a SQL view, and having PostgreSQL enforce that queries don't change state with read-only transactions, with real SQL and the 25006 error.

7 Nov 2026 14 min 4
A Separate Read Model: Materialized Views, Synchronization, and Living with Eventual Consistency
Software Architecture PART 03

A Separate Read Model: Materialized Views, Synchronization, and Living with Eventual Consistency

A separate read model stores the screen's row precomputed from domain events; updated in the same transaction it stays immediately consistent, updated asynchronously in a separate database you have to live with eventual consistency. Inline projections, PostgreSQL materialized views, an asynchronous projector with a checkpoint, waiting on a position for read-your-own-writes, idempotent updates and a full rebuild, with real output.

7 Nov 2026 14 min 4
What Is Event Sourcing? Storing What Happened Instead of State
Software Architecture PART 04

What Is Event Sourcing? Storing What Happened Instead of State

Event Sourcing stores what happened in an append-only event stream instead of the latest state, and derives state by folding those events. Using Bookstore's stock ledger: rehydration, audit, temporal queries, optimistic concurrency with an expected version, why an event store is not a message broker, why it goes together with CQRS, and its real costs.

7 Nov 2026 14 min 5
Event-Sourced Aggregates with the Decider Pattern: decide, evolve, and Given-When-Then Tests
Software Architecture PART 05

Event-Sourced Aggregates with the Decider Pattern: decide, evolve, and Given-When-Then Tests

The decider pattern splits an event-sourced model's decision logic into two pure functions: Decide produces new events from a command and a state, Evolve produces a new state from a state and an event. A decider for the stock ledger with C# 14 switch expressions, moving time into the command with TimeProvider, database-free Given-When-Then tests and a comparison with the OOP aggregate style, with real test output.

7 Nov 2026 14 min 4
Working with an Event Store: Append, Optimistic Concurrency, and Streams with Marten and PostgreSQL
Software Architecture PART 06

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.

7 Nov 2026 16 min 4
Projections: Building Read Models with Inline, Async, and Live Projections
Software Architecture PART 07

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.

7 Nov 2026 13 min 5
Event Versioning and Snapshots: Changing Event Schemas Without Breaking History
Software Architecture PART 08

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.

7 Nov 2026 12 min 4
The Hard Parts of Event Sourcing: GDPR, Unique Constraints, and Dynamic Consistency Boundaries
Software Architecture PART 09

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.

7 Nov 2026 14 min 3
When Are CQRS and Event Sourcing Unnecessary? Anti-Patterns and a Decision Guide
Software Architecture PART 10

When Are CQRS and Event Sourcing Unnecessary? Anti-Patterns and a Decision Guide

CQRS and event sourcing are unnecessary for plain CRUD, MVPs, static reference data, real-time consistent views, and inexperienced teams; the decision is made separately for each bounded context. Bookstore's context map, a decision flow for CQRS levels 1/2/3 and event sourcing, and four anti-patterns: CQRS ceremony on a single database, event sourcing everywhere, state-change events, and using internal events as an integration contract.

7 Nov 2026 11 min 4
Blog Map