CQRS way

  • Typical architecture pros & cons
  • CQRS concept
  • Code example
    • NEventStore
    • CommonDomain
  • Pros & cons
  • Results





Based on Greg Young's notes and OMD Vision team  experience  

Typical architecture

  • ORM (NH, EF)
  • MS SQL
  • DDD (Entity, Repository, Service)
  • WebApi CRUD (REST) services


What the problem?



Problems

  • You can’t do DDD
    • Anemic domain model
    • No aggregates
    • CRUD
    • As result Business logic is blur (server, client, dev mind)
  • Lazy loading
  • Query optimization is punishment
    • One repository method for different reason
    • Leads to entity pollution
  • Data loss due to storing last state
  • Doesn’t scale
    • Very expensive horizontal scale, and limited vertical
  • Transaction and locks for readers

Why do we use

  • Experience, it works at least
  • Devs understand it
  • Mature
    • You can google any problem
  • Tooling
  • Microsoft, Oracle propagation
    • They benefit from this architecture!
  • There isn't any other option
    • or is there?

Free your mind

  • Save state vs history
  • We are lucky, CQRS started to live in .NET
  • Greg Young and Jonathan Oliver are fathers
  • CQRS completely different approach
    • With pros and cons, all about trade off
    • No silver bullet
  • Time for app to lose weight

How?

CQRS

  • Command Query Responsibility Segregation concept
  • Pros and cons
  • Production proven implementation
    • NEventStore (MS SQL, Mongo)
    • CommonDomain

Concept

Command Query Responsibility Segregation

Concept


Aggregate

  • Reply 
  • Snapshot

Horizontal scale


Advantages #1

  • Simplicity due to real DDD
    • Aggregate is isolated (logic inside one class)
    • Has solid public interface for write only (no pollution)
    • Simple unit tests
  • Fast read
    • Thin read layer on top of data store
    • Read database should be at Web server (MS SQL + Shared Memory protocol = ~50% increase)
  • Flexible read optimization
    • For highload projections MS SQL can be replaced with Redis, Mongo without any problem.
  • Time-travel
    • Reproduce bug

Advantages #2

  • Easy horizontal scaling
    • Read side performance linear increases by adding new nodes
    • Geo-scaling, due to 100-200ms delay
    • On-demand horizontal scaling can be applied
  • No data loss due to storing all events
    • Audit for free
    • Analytics on the board
    • Sophisticated reporting
      • Users who created >10 companies per month during 3 month at 2012
      • Activity stream
  • Integration for free due to event sourcing

Disadvantages #1

  • Hard to understand at the beginning (eventual vs transactional consistency)
  • Feature implementation takes more time
    • Extra code should be written (command, event, projection)
  • Fit for system with <30% writes
  • Hot fixes slower, no possibility to run SQL to fix
  • Write side doesn't scale, performance fixed
    • Can be increased by snapshots

Disadvantages #2

  • Long projection rebuild
    • Increases all the time, can be optimized by dev
  • Read side is later than write side
    • Can be resolved by ManualResetEvent or SignalR
  • Painful aggregate refactoring
    • Event can not be changed (Converting events, compensation events)

CQRS code examples:

  • Controller write
  • Command
  • Command handler
  • Aggregate
  • Event
  • Projection
  • Controller read
  • Write database

Controller write



Command

Command handler

Aggregate

Event

Projection


Controller read

Write database

OMD Vision results

  • MS SQL 2012, ASP.NET MVC 4, ServiceStack.OrmLite 3
  • Read request ~ 30ms (prod) ~ 15ms (local)
  • Write request
    • 100ms (prod) 30ms (local)
    • 200ms fat aggregate (prod) 60ms(local)
  • 1.3m events
  • 0.5m commits
  • The most fat aggregates:
    • 1st = 14 054 events
    • 2nd = 7 778 events
    • 3rd = 7 449 events
  • 65 projections 110 tables
  • Full rebuild duration ~1d

Questions

Links

CQRS overview

By Vladimir Gaevoy

CQRS overview

  • 4,560