CQRS
Separating reads from writes — and knowing it doesn't require separate databases.
Command Query Responsibility Segregation: separate models (and often separate code paths) for writes (Commands — change state, don't return data) and reads (Queries — return data, don't change state). This is Clean Code's Command-Query Separation applied at the architecture level, not just per-method.
Important nuance to state clearly, because it's the #1 CQRS misconception: CQRS does not
require two separate databases or event sourcing. The simplest, very common form is "same database,
different code paths": write side uses your rich domain model + EF Core change tracking; read side
uses lean, AsNoTracking() projection queries straight into DTOs, often bypassing the domain model
entirely for speed. Full CQRS with separate read/write stores (and eventual consistency between them,
usually synced via events) is a heavier architectural commitment you'd reach for under real read/write
load or model divergence — not a default.
Combined with MediatR: IRequest queries and IRequest (no response, or a simple result) commands,
routed through the same mediator pipeline, is the standard .NET implementation shape.
// Command — changes state, minimal/no return data
public record PlaceOrderCommand(string CustomerId, List<OrderLine> Lines) : IRequest<Guid>;
// Query — reads only, own lean projection
public record GetOrderSummaryQuery(Guid OrderId) : IRequest<OrderSummaryDto>;