CQRS

CQRS and Event Sourcing in .NET 8: Best Practices for Scalable Applications

Scalable Architecture Through CQRS and Event Sourcing in .NET 8

  • Separation of concerns — because one method shouldn’t do 17 things .
  • Auditability — for when the business asks, “How did this happen?”
  • Scalability — because we started with 10 users and now we have 10,000 (and counting).
  • Maintainability — for the sake of my future self, who deserves kindness.

The Moment I Snapped (and Discovered Event Sourcing)

Let me paint a picture.
It’s 11:47 PM. My dog is asleep on my keyboard. My coffee is as cold as my patience.
And I’m staring at an ever-growing OrderService class with over 1,300 lines of code.

I mutter to myself, “There has to be a better way.”

My wife hears this and, without looking up from her book, replies:
“You’ve said that 43 times this week.”

And that, dear reader, is when I discovered CQRS and Event Sourcing.
Or as I now call them: the best worst decision I’ve ever made.

Environment Setup (a.k.a. The Fun Part… Sorta)

If you’re on .NET 8 (which you absolutely should be), here’s the basic stack I used:

  • .NET 8 SDK
  • ASP.NET Core Web API
  • MediatR (for the CQRS magic)
  • EventStoreDB or even plain ol’ PostgreSQL with an event table
  • Entity Framework Core (for projections and read models)
  • Docker (because dev machines must suffer equally)

You’ll also want a nice logging solution (I went with Serilog) because debugging without logs is like reading a mystery novel with half the pages missing.

Best Practices (Written in Coffee and Regret)

  1. Don’t CQRS all the things.
    Use it where complexity justifies the pattern. Don’t turn your “Contact Us” form into a distributed system.
  2. Treat events as facts.
    You can’t go back and say, “Nah, that UserDeletedEvent didn’t happen.” You committed. Be okay with that. Be like Batman.
  3. Keep your commands boring.
    Commands shouldn’t do anything fancy. No email sending. No Slack notifications. Just validate, persist, publish events — like a librarian that doesn’t gossip.
  4. Queries should fly.
    Read models can be denormalized. Use projections. Store data how you want to read it, not how the domain model demands it. Think Netflix recommendations, not SQL JOIN puzzles.
  5. Snapshots save lives (and CPU).
    Replaying 10,000 events to get the current state is like re-watching 10 seasons of a show to understand one character’s backstory. Use snapshots to speed things up.

Benefits I Actually Enjoy

  • Clear separation of concerns
  • Versioned history of data
  • Flexibility in read models
  • Massive testability improvement
  • Post-facto features (like “undo last action” or “replay last order state”)

Bonus:
It made me look like a wizard in meetings.
“How did you know that user changed their shipping address five times in 30 minutes?”
Me: “The events told me.”

Cons (Don’t Say I Didn’t Warn You)

  • Steep learning curve — Like, Himalayan steep.
  • Tooling is still maturing — Some debugging steps felt like black magic.
  • More moving parts — Events, projections, snapshotting, dispatching.
  • Overkill for simple CRUD apps — Don’t bring a bazooka to a CodePen fight.

You will over-engineer.
You will refactor.
And you will cry (just a little).

Scope: When to Use CQRS + Event Sourcing

Use it when:

  • You’re building highly complex domains with deep business logic
  • You need event-driven architecture (microservices love this)
  • Auditability and replayability are essential
  • Your app is write-heavy but read-explosive (think social feeds, e-commerce, etc.)

Avoid if:

  • It’s a small CRUD app with no scalability pain in sight
  • You just want to ship something fast without future-you hunting bugs in projections

Conclusion: Why I’d Do It All Over Again (Mostly)

CQRS and Event Sourcing in .NET 8 isn’t for everyone — but for those battling complexity at scale, it’s like finding a map in the middle of a labyrinth.

Yes, it adds layers.
Yes, it takes longer to learn.
But when you see the payoff — when your app scales like a beast, when your data tells a story, when the business says “Can we do this?” and you say “Already done” — it’s worth every painful refactor.

Visit more post-Flutter 4.0 – Developing Apps

2 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *