Query Responsibility Segregation pattern is an architectural pattern that allows to represent system’s data in multiple persistent models. It is similar to Ports & Adapters pattern but it differs in a way the data is managed. It was initially defined to address limitations of Event Sourcing Pattern where it is only possible to query event of one aggregate instance at the time.

graph TD  
    Client[Client]  
      
    subgraph "Command Side"  
    CmdAPI[Command API]  
    CmdHandler[Command Handler]  
    WriteRepo[Write Repository]  
    end  
      
    subgraph "Query Side"  
    QueryAPI[Query API]  
    QueryHandler[Query Handler]  
    ReadRepo[Read Repository]  
    end  
      
    Client -->|Write Request| CmdAPI  
    Client -->|Read Request| QueryAPI  
      
    CmdAPI -->|Create/Update User| CmdHandler  
    CmdHandler -->|Persist Changes| WriteRepo  
    WriteRepo -->|Sync| ReadRepo  
      
    QueryAPI -->|Get User Data| QueryHandler  
    QueryHandler -->|Fetch Data| ReadRepo  
      
    style Client fill:#f9f,stroke:#333,stroke-width:2px  
    style CmdAPI fill:#bbf,stroke:#333,stroke-width:2px  
    style QueryAPI fill:#bfb,stroke:#333,stroke-width:2px  
    style CmdHandler fill:#bbf,stroke:#333,stroke-width:2px  
    style QueryHandler fill:#bfb,stroke:#333,stroke-width:2px  
    style WriteRepo fill:#fbb,stroke:#333,stroke-width:2px  
    style ReadRepo fill:#bfb,stroke:#333,stroke-width:2px  

Command

Command is a write model that implements a business logic, validates rules and enforces invariants. This model represents strongly consistent data (source of truth). It should always let the caller know whether they succeed or failed, and it should provide a clear information why it did fail and if it’s caller’s fault, it should let them know how to fix that command.

Query

It is a read model, a pre-cached projection that lives in a database, flat file or in-memory cache. Read models can create projections synchronously and asynchronously

Synchronous Projection

Whenever the source tables are updated, changes are being reflected in the pre-cached views straight away by subscribing to the table. This requires a creation of projection model that is responsible for regenerationg an updating system’s read models. When write model is updated, the procetion engine uses last processed record to add and modify records.

Asynchronous Projections

They are similar to synchronous projections, but the main difference is that they are triggered asynchronously. The main challenge with using those is that they can be crmblesome in distributed computing. When messages are duplicated or out of order, projections may be inconsistent. Because of that, synchronous projection is a better option.

When to use it

Because this pattern supports Domain Driven Design core values of working with the most effective models for a task at hand, it should be used when using DDD. Also, it it works well with Event Sourcing Pattern. Also, this pattern is very useful when different technologies need to be used for different task (REST, Search Engines etc.).