<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Thu Ngan Pham</title>
    <description>The latest articles on DEV Community by Thu Ngan Pham (@thunganpham).</description>
    <link>https://dev.to/thunganpham</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3008232%2F070e5b65-8e84-4f77-a55c-1f4cfab4bc36.jpeg</url>
      <title>DEV Community: Thu Ngan Pham</title>
      <link>https://dev.to/thunganpham</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thunganpham"/>
    <language>en</language>
    <item>
      <title>CQRS (Command Query Responsibility Segregation) STRUCTURE ? (PART 2)</title>
      <dc:creator>Thu Ngan Pham</dc:creator>
      <pubDate>Tue, 27 May 2025 13:41:36 +0000</pubDate>
      <link>https://dev.to/thunganpham/cqrs-structure-why-not--4706</link>
      <guid>https://dev.to/thunganpham/cqrs-structure-why-not--4706</guid>
      <description>&lt;p&gt;Below are the CRUD operations surrounding the Post module, totaling up to 282 lines of code. This can lead to several issues such as &lt;strong&gt;violations of the SRP principle in SOLID, race conditions, inconsistent states, lock conflicts, and so on.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvvolw6plc2t12e2tanag.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvvolw6plc2t12e2tanag.png" alt="Image description" width="583" height="1242"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These issues can be addressed by reorganizing the code — &lt;strong&gt;clearly separating services, using transactions, applying Optimistic/Pessimistic Locking, and offloading auxiliary logic to Events or Queues.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Additionally, you might consider adopting the CQRS architecture, a pattern that clearly separates read and write operations. When combined with principles such as event sourcing, proper locking, and asynchronous processing, CQRS can help the system become more scalable, manageable, and less prone to complex errors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note: This is just a sample source code for Post, following a flat comment structure similar to Google Maps&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs6fx56wtcy2tm4h1imm9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs6fx56wtcy2tm4h1imm9.png" alt="Image descript" width="597" height="919"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1er46c90hnwcup0huedx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1er46c90hnwcup0huedx.png" alt="Image description" width="575" height="588"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdua33akbcvbeb93tmsyb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdua33akbcvbeb93tmsyb.png" alt="Image descrption" width="800" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm2lfvjmrwj605drrj1bg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm2lfvjmrwj605drrj1bg.png" alt="Image desciption" width="800" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa0wug2eg74ttgewl8btj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa0wug2eg74ttgewl8btj.png" alt="Imag description" width="800" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With CQRS, the read and write flows are separated, allowing each component to have a single, focused responsibility. Each &lt;strong&gt;CommandHandler&lt;/strong&gt; is responsible solely for performing actions (create, update, delete), while each &lt;strong&gt;QueryHandler&lt;/strong&gt; is only concerned with data retrieval.&lt;/p&gt;

&lt;p&gt;These handlers typically contain only a single function for processing, making the codebase clean and elegant, avoiding the "God service" anti-pattern. It also improves performance, as the read flow can use a dedicated database, isolated from the complex operations in the write flow.&lt;/p&gt;

&lt;p&gt;By separating read and write logic, it's also easier to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Apply transactions to CommandHandlers&lt;/li&gt;
&lt;li&gt;Use locking strategies (optimistic/pessimistic) in writes to avoid conflicts&lt;/li&gt;
&lt;li&gt;Isolate side effects of write actions, reducing the risk of affecting the overall system state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a result, the codebase becomes easier to scale and maintain.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>cqrs</category>
      <category>backend</category>
      <category>backenddevelopment</category>
    </item>
    <item>
      <title>Pattern CQRS (Command Query Responsibility Segregation) combined with Event Sourcing (Part 1)</title>
      <dc:creator>Thu Ngan Pham</dc:creator>
      <pubDate>Wed, 02 Apr 2025 15:04:18 +0000</pubDate>
      <link>https://dev.to/thunganpham/pattern-cqrs-command-query-responsibility-segregation-ket-hop-event-sourcing-phan-1-kjk</link>
      <guid>https://dev.to/thunganpham/pattern-cqrs-command-query-responsibility-segregation-ket-hop-event-sourcing-phan-1-kjk</guid>
      <description>&lt;h2&gt;
  
  
  CQRS Pattern (Command Query Responsibility Segregation) Combined with Event Sourcing
&lt;/h2&gt;

&lt;p&gt;In traditional architectures, applications interact with the database using CRUD operations for both reading and writing. However, as applications scale and the number of requests increases, this approach can lead to performance bottlenecks. Designing the system with a single data model can result in several issues:&lt;/p&gt;

&lt;h2&gt;
  
  
  Lock Contention
&lt;/h2&gt;

&lt;p&gt;Before diving into CQRS, let’s discuss "&lt;strong&gt;resource contention.&lt;/strong&gt;" Consider the following example:&lt;br&gt;
A user clicks the BOOK button, triggering two API calls:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;GET&lt;/strong&gt; /flights/seats returns the number of available seats.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;POST&lt;/strong&gt; /flights/book reserves a seat.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If two users attempt to book the same seat (e.g., seat A1) simultaneously, both requests might retrieve outdated data and successfully reserve the same seat. To prevent this, the system must implement locking mechanisms to maintain data integrity. However, locking slows down the system because requests must wait for one another to complete before proceeding.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Mismatch
&lt;/h2&gt;

&lt;p&gt;Data mismatch occurs when the structure of data used for reading and writing is not well aligned, leading to performance degradation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Write operations:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When a user creates or updates a post, the system must store all related data, such as title, content, tags, likes, authorInfo, and comments. However, some fields, like authorInfo, may not be necessary for most read operations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Read operations:&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;If a user only wants to see a list of posts (e.g., displaying only the title and number of likes), querying unnecessary fields like authorInfo and comments increases the data load.&lt;/p&gt;

&lt;p&gt;To address this, developers may use data references, caching, or document duplication, but these approaches complicate data integrity maintenance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance Problems
&lt;/h2&gt;

&lt;p&gt;A traditional architecture that relies on a single data model for both reading and writing can face several performance issues:&lt;br&gt;
Database Overload: Handling simultaneous read and write requests can strain the database.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Query Complexity:&lt;/strong&gt; Retrieving product details and comments in an e-commerce system may introduce high query latency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scalability Issues:&lt;/strong&gt; During peak traffic, simultaneous read and write operations can cause bottlenecks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lack of Optimization:&lt;/strong&gt; Read and write operations can interfere with each other, reducing overall system performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security Challenges
&lt;/h2&gt;

&lt;p&gt;Managing security becomes more complex when entities handle both read and write operations. Overlapping responsibilities may expose sensitive data in unintended scenarios.&lt;/p&gt;

&lt;p&gt;Although each of the issues above has individual solutions, CQRS simplifies the overall architecture by separating read and write operations. This separation enhances performance and makes it easier to handle complex scenarios. By implementing improvements such as client-side validation, optimized server logic, and asynchronous processing, developers can optimize both read and write operations, reduce errors, and provide a better user experience.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In the next article, I will discuss the architecture and implementation of CQRS combined with Event Sourcing.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
    </item>
  </channel>
</rss>
