Skip to main content

CQRS Pattern in PearDrop

Command Query Responsibility Segregation separates data modification (writes) from data retrieval (reads) into two distinct, optimized systems.

In PearDrop, the write side uses Domain-Driven Design principles to model complex business logic through aggregates and domain events, while the read side uses optimized projections and queries for fast data retrieval.

Architecture Overview

CQRS structures your application into two optimized paths:

┌─────────────────────────────────────┐        ┌──────────────────────────┐
│ WRITE SIDE (Commands) │ │ READ SIDE (Queries) │
├─────────────────────────────────────┤ ├──────────────────────────┤
│ • Domain-Driven Design │ │ • Optimized for Speed │
│ • Aggregates enforce invariants │ │ • Denormalized │
│ • Domain Events coordinate changes │ │ • Projections │
│ • Integration Events enable │ │ • Cached results │
│ cross-module communication │ │ • Query Optimization │
│ │ │ │
│ UpdateEquipmentCommand │ │ GetEquipmentByIdQuery │
│ ↓ │ │ ↓ │
│ Handler loads aggregate │ │ Handler queries read │
│ ↓ │ │ projection │
│ Aggregate validates & changes state │ │ ↓ │
│ ↓ │ │ Returns DTO │
│ SaveChanges to database │ │ │
│ ↓ │ │ │
│ Publish integration events │ │ │
│ ↓ (triggers read updates) │ │ │
└─────────────────────────────────────┘ └──────────────────────────┘
Consistency Eventual Consistency Queries
Strong Optimized

Benefits

BenefitExplanation
Clear IntentCommands explicitly represent intent ("Create", "Update"); queries explicitly represent questions ("Get", "List")
Optimized ReadsRead models are denormalized and indexed specifically for common queries
Optimized WritesWrite models focus on business logic and consistency
ScalabilityScale read replicas independently from write operations
Event-DrivenNatural fit for event sourcing and audit trails
TestingCommands and queries tested independently with clear responsibilities

Write Side: Design Your Domain

The write side uses Domain-Driven Design to model your business logic:

  • Aggregates: Clusters of entities that enforce business invariants
  • Commands: Intent-driven representations of what the user wants to do
  • Domain Events: Changes that occurred within an aggregate
  • Integration Events: Cross-module communication for eventual consistency

→ Learn more: Write Side (Domain-Driven Design)

Read Side: Optimize Your Queries

The read side provides optimized access to data:

  • Read Models: Denormalized projections optimized for specific queries
  • Queries: Questions asked without modifying state
  • DTOs: Data transfer objects shaped for UI clients
  • Caching: Optional caching layer for frequently accessed data

→ Learn more: Read Side

When to Use CQRS

Use CQRS when:

  • Your app has complex business logic with many business rules
  • You have different optimization needs for reads vs. writes
  • You want to event source your data
  • You need independent scaling of read and write workloads
  • You have integration across multiple modules or bounded contexts

Consider alternatives for:

  • Simple CRUD applications with minimal business logic
  • Traditional n-tier architectures (models can be unified)
  • Very simple applications that don't need optimization