Separate intent, not infrastructure by default
A command expresses a requested state change. A query reads a projection and should not mutate business state. Keeping the two paths explicit makes authorization, validation, transaction boundaries, and response shape easier to follow.
Organize around use cases
A feature can group its query or command with its handler and related result types. Controllers translate HTTP contracts into requests and send them through a mediator. Handlers coordinate business rules and call feature ports; Infrastructure implements persistence.
A mediator does not require microservices
MediatR dispatches in-process requests. It does not create a network boundary, separate deployment, or independent database. A single application can use this organization while sharing a database transaction where consistency requires it.
Keep the read path proportionate
A query can project directly to a screen-specific result when that makes the use case clearer. Avoid generic repositories, duplicate databases, or a pipeline of abstractions without a concrete need.
Interview takeaway
Walk through one request from controller to handler to persistence and back. Identify where the transaction begins and which part owns each validation rule.