{"id":488,"date":"2026-05-30T05:55:00","date_gmt":"2026-05-30T05:55:00","guid":{"rendered":"https:\/\/harshad-sonawane.com\/blog\/?p=488"},"modified":"2026-05-16T14:17:35","modified_gmt":"2026-05-16T14:17:35","slug":"implementing-cqrs-and-event-sourcing-in-spring-boot","status":"publish","type":"post","link":"https:\/\/harshad-sonawane.com\/blog\/implementing-cqrs-and-event-sourcing-in-spring-boot\/","title":{"rendered":"Implementing CQRS and Event Sourcing in Spring Boot"},"content":{"rendered":"<p data-start=\"55\" data-end=\"459\">Modern enterprise applications often struggle with scalability, complex business workflows, and maintaining consistency across <a href=\"https:\/\/harshad-sonawane.com\/blog\/eventual-consistency-distributed-java-systems\/\">distributed systems<\/a>. Traditional CRUD-based architectures become difficult to manage as applications evolve and business rules become more sophisticated. This is where CQRS (Command Query Responsibility Segregation) and Event Sourcing emerge as powerful architectural patterns.<\/p>\n<p data-start=\"461\" data-end=\"726\">In this blog, we will explore how to implement CQRS and Event Sourcing using <span class=\"hover:entity-accent entity-underline inline cursor-pointer align-baseline\"><span class=\"whitespace-normal\"><a href=\"https:\/\/harshad-sonawane.com\/blog\/audit-logging-in-java-microservices-techniques-and-compliance-tips\/\">Spring Boot<\/a><\/span><\/span>, understand the core concepts, examine practical implementation strategies, and evaluate when these patterns are suitable for real-world applications.<\/p>\n<hr data-start=\"728\" data-end=\"731\" \/>\n<h1 data-section-id=\"1ko5tn5\" data-start=\"733\" data-end=\"753\">Understanding CQRS<\/h1>\n<p data-start=\"755\" data-end=\"883\">CQRS stands for Command Query Responsibility Segregation. The primary idea is to separate read operations from write operations.<\/p>\n<p data-start=\"885\" data-end=\"1009\">Instead of using a single model for both reading and writing data, CQRS divides the application into two independent models:<\/p>\n<ul data-start=\"1011\" data-end=\"1114\">\n<li data-section-id=\"10ws2y\" data-start=\"1011\" data-end=\"1074\">Command Model \u2192 Handles create, update, and delete operations<\/li>\n<li data-section-id=\"1rf198y\" data-start=\"1075\" data-end=\"1114\">Query Model \u2192 Handles read operations<\/li>\n<\/ul>\n<p data-start=\"1116\" data-end=\"1233\">This separation allows each side to evolve independently and optimizes performance, scalability, and maintainability.<\/p>\n<h2 data-section-id=\"7gg9k8\" data-start=\"1235\" data-end=\"1262\">Traditional CRUD vs CQRS<\/h2>\n<h3 data-section-id=\"1w136a3\" data-start=\"1264\" data-end=\"1293\">Traditional CRUD Approach<\/h3>\n<p data-start=\"1295\" data-end=\"1325\">In a typical CRUD application:<\/p>\n<ul data-start=\"1327\" data-end=\"1497\">\n<li data-section-id=\"1aax0b1\" data-start=\"1327\" data-end=\"1369\">The same entity handles reads and writes<\/li>\n<li data-section-id=\"19t3m13\" data-start=\"1370\" data-end=\"1410\">Business logic becomes tightly coupled<\/li>\n<li data-section-id=\"1mn46ze\" data-start=\"1411\" data-end=\"1462\">Scaling read-heavy applications becomes difficult<\/li>\n<li data-section-id=\"mungwz\" data-start=\"1463\" data-end=\"1497\">Complex joins impact performance<\/li>\n<\/ul>\n<h3 data-section-id=\"d0rodf\" data-start=\"1499\" data-end=\"1516\">CQRS Approach<\/h3>\n<p data-start=\"1518\" data-end=\"1528\">With CQRS:<\/p>\n<ul data-start=\"1530\" data-end=\"1669\">\n<li data-section-id=\"sp0aez\" data-start=\"1530\" data-end=\"1553\">Commands modify state<\/li>\n<li data-section-id=\"1h14dsq\" data-start=\"1554\" data-end=\"1577\">Queries retrieve data<\/li>\n<li data-section-id=\"1yddasw\" data-start=\"1578\" data-end=\"1618\">Separate models optimize each use case<\/li>\n<li data-section-id=\"1401x6l\" data-start=\"1619\" data-end=\"1669\">Read and write databases can scale independently<\/li>\n<\/ul>\n<hr data-start=\"1671\" data-end=\"1674\" \/>\n<h1 data-section-id=\"1ykd8ra\" data-start=\"1676\" data-end=\"1706\">Understanding Event Sourcing<\/h1>\n<p data-start=\"1708\" data-end=\"1827\">Event Sourcing stores every state change as a sequence of immutable events instead of persisting only the latest state.<\/p>\n<p data-start=\"1829\" data-end=\"1849\">Rather than storing:<\/p>\n<div class=\"relative w-full mt-4 mb-1\">\n<div class=\"\">\n<div class=\"relative\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"border border-token-border-light border-radius-3xl corner-superellipse\/1.1 rounded-3xl\">\n<div class=\"h-full w-full border-radius-3xl bg-token-bg-elevated-secondary corner-superellipse\/1.1 overflow-clip rounded-3xl lxnfua_clipPathFallback\">\n<div class=\"pointer-events-none absolute end-1.5 top-1 z-2 md:end-2 md:top-1\"><\/div>\n<div class=\"relative\">\n<div class=\"pe-11 pt-3\">\n<div class=\"relative z-0 flex max-w-full\">\n<div id=\"code-block-viewer\" dir=\"ltr\" class=\"q9tKkq_viewer cm-editor z-10 light:cm-light dark:cm-light flex h-full w-full flex-col items-stretch \u037cd \u037cr\">\n<div class=\"cm-scroller\">\n<pre class=\"cm-content q9tKkq_readonly m-0\"><code><span>Account Balance = 5000<\/span><\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"\">\n<div class=\"\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p data-start=\"1887\" data-end=\"1905\">The system stores:<\/p>\n<div class=\"relative w-full mt-4 mb-1\">\n<div class=\"\">\n<div class=\"relative\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"border border-token-border-light border-radius-3xl corner-superellipse\/1.1 rounded-3xl\">\n<div class=\"h-full w-full border-radius-3xl bg-token-bg-elevated-secondary corner-superellipse\/1.1 overflow-clip rounded-3xl lxnfua_clipPathFallback\">\n<div class=\"pointer-events-none absolute end-1.5 top-1 z-2 md:end-2 md:top-1\"><\/div>\n<div class=\"relative\">\n<div class=\"pe-11 pt-3\">\n<div class=\"relative z-0 flex max-w-full\">\n<div id=\"code-block-viewer\" dir=\"ltr\" class=\"q9tKkq_viewer cm-editor z-10 light:cm-light dark:cm-light flex h-full w-full flex-col items-stretch \u037cd \u037cr\">\n<div class=\"cm-scroller\">\n<pre class=\"cm-content q9tKkq_readonly m-0\"><code><span>AccountCreated<\/span>\n<span>MoneyDeposited<\/span>\n<span>MoneyWithdrawn<\/span>\n<span>MoneyDeposited<\/span><\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"\">\n<div class=\"\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p data-start=\"1980\" data-end=\"2035\">The current state is reconstructed by replaying events.<\/p>\n<h2 data-section-id=\"c4z3cs\" data-start=\"2037\" data-end=\"2066\">Benefits of Event Sourcing<\/h2>\n<h3 data-section-id=\"fucq0w\" data-start=\"2068\" data-end=\"2092\">Complete Audit Trail<\/h3>\n<p data-start=\"2094\" data-end=\"2131\">Every change is recorded permanently.<\/p>\n<h3 data-section-id=\"18ll5yu\" data-start=\"2133\" data-end=\"2153\">Temporal Queries<\/h3>\n<p data-start=\"2155\" data-end=\"2213\">You can reconstruct the system state at any point in time.<\/p>\n<h3 data-section-id=\"8hnoao\" data-start=\"2215\" data-end=\"2235\">Better Debugging<\/h3>\n<p data-start=\"2237\" data-end=\"2294\">Events provide a historical timeline for troubleshooting.<\/p>\n<h3 data-section-id=\"lbxx2z\" data-start=\"2296\" data-end=\"2324\">Event-Driven Integration<\/h3>\n<p data-start=\"2326\" data-end=\"2377\">Other <a href=\"https:\/\/harshad-sonawane.com\/blog\/java-applications-edge-iot-architecture\/\">microservices<\/a> can subscribe to domain events.<\/p>\n<hr data-start=\"2379\" data-end=\"2382\" \/>\n<h1 data-section-id=\"10wr5zs\" data-start=\"2384\" data-end=\"2418\">CQRS and Event Sourcing Together<\/h1>\n<p data-start=\"2420\" data-end=\"2520\">CQRS and Event Sourcing are often implemented together because they complement each other naturally.<\/p>\n<ul data-start=\"2522\" data-end=\"2647\">\n<li data-section-id=\"1md082w\" data-start=\"2522\" data-end=\"2548\">Commands generate events<\/li>\n<li data-section-id=\"1h2vbcn\" data-start=\"2549\" data-end=\"2587\">Events are stored in the event store<\/li>\n<li data-section-id=\"1r6bu60\" data-start=\"2588\" data-end=\"2647\">Read models are updated asynchronously using those events<\/li>\n<\/ul>\n<p data-start=\"2649\" data-end=\"2690\">This architecture is highly suitable for:<\/p>\n<ul data-start=\"2692\" data-end=\"2833\">\n<li data-section-id=\"13b6b3s\" data-start=\"2692\" data-end=\"2709\">Banking systems<\/li>\n<li data-section-id=\"l8t8vs\" data-start=\"2710\" data-end=\"2739\">E-commerce order processing<\/li>\n<li data-section-id=\"bstjrl\" data-start=\"2740\" data-end=\"2762\">Inventory management<\/li>\n<li data-section-id=\"144wenr\" data-start=\"2763\" data-end=\"2780\">Booking systems<\/li>\n<li data-section-id=\"iszrl4\" data-start=\"2781\" data-end=\"2805\">Financial applications<\/li>\n<li data-section-id=\"1hoanj\" data-start=\"2806\" data-end=\"2833\">Distributed microservices<\/li>\n<\/ul>\n<hr data-start=\"2835\" data-end=\"2838\" \/>\n<h1 data-section-id=\"1lwh98m\" data-start=\"2840\" data-end=\"2865\">High-Level Architecture<\/h1>\n<p data-start=\"2867\" data-end=\"2917\">A CQRS + Event Sourcing system typically contains:<\/p>\n<ol data-start=\"2919\" data-end=\"3052\">\n<li data-section-id=\"1ujjch1\" data-start=\"2919\" data-end=\"2933\">Command API<\/li>\n<li data-section-id=\"1ok7zs\" data-start=\"2934\" data-end=\"2946\">Aggregate<\/li>\n<li data-section-id=\"t1ue5j\" data-start=\"2947\" data-end=\"2963\">Domain Events<\/li>\n<li data-section-id=\"ctoato\" data-start=\"2964\" data-end=\"2978\">Event Store<\/li>\n<li data-section-id=\"57f2e4\" data-start=\"2979\" data-end=\"2997\">Event Publisher<\/li>\n<li data-section-id=\"1n9mnaw\" data-start=\"2998\" data-end=\"3012\">Query Model<\/li>\n<li data-section-id=\"8caa0a\" data-start=\"3013\" data-end=\"3035\">Projection Handlers<\/li>\n<li data-section-id=\"1o2bfgk\" data-start=\"3036\" data-end=\"3052\">Read Database<\/li>\n<\/ol>\n<hr data-start=\"3054\" data-end=\"3057\" \/>\n<h1 data-section-id=\"7qiefi\" data-start=\"3059\" data-end=\"3077\">Technology Stack<\/h1>\n<p data-start=\"3079\" data-end=\"3116\">For this implementation, we will use:<\/p>\n<ul data-start=\"3118\" data-end=\"3295\">\n<li data-section-id=\"2kc2rb\" data-start=\"3118\" data-end=\"3127\"><a href=\"https:\/\/harshad-sonawane.com\/blog\/reduce-cloud-costs-java-applications\/\">Java<\/a> 21<\/li>\n<li data-section-id=\"lyf7sl\" data-start=\"3128\" data-end=\"3167\"><span class=\"hover:entity-accent entity-underline inline cursor-pointer align-baseline\"><span class=\"whitespace-normal\">Spring Boot<\/span><\/span><\/li>\n<li data-section-id=\"1p430yx\" data-start=\"3168\" data-end=\"3180\">Spring Web<\/li>\n<li data-section-id=\"v6agmq\" data-start=\"3181\" data-end=\"3198\">Spring Data JPA<\/li>\n<li data-section-id=\"wlg39x\" data-start=\"3199\" data-end=\"3238\"><span class=\"hover:entity-accent entity-underline inline cursor-pointer align-baseline\"><span class=\"whitespace-normal\">Apache <a href=\"https:\/\/harshad-sonawane.com\/blog\/building-real-time-applications-java-architecture-frameworks\/\">Kafka<\/a><\/span><\/span><\/li>\n<li data-section-id=\"1etlrsl\" data-start=\"3239\" data-end=\"3278\"><span class=\"hover:entity-accent entity-underline inline cursor-pointer align-baseline\"><span class=\"whitespace-normal\">PostgreSQL<\/span><\/span><\/li>\n<li data-section-id=\"1pb87nk\" data-start=\"3279\" data-end=\"3287\">Lombok<\/li>\n<li data-section-id=\"16vtg8p\" data-start=\"3288\" data-end=\"3295\">Maven<\/li>\n<\/ul>\n<hr data-start=\"3297\" data-end=\"3300\" \/>\n<h1 data-section-id=\"8qmyyu\" data-start=\"3302\" data-end=\"3321\">Project Structure<\/h1>\n<div class=\"relative w-full mt-4 mb-1\">\n<div class=\"\">\n<div class=\"relative\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"border border-token-border-light border-radius-3xl corner-superellipse\/1.1 rounded-3xl\">\n<div class=\"h-full w-full border-radius-3xl bg-token-bg-elevated-secondary corner-superellipse\/1.1 overflow-clip rounded-3xl lxnfua_clipPathFallback\">\n<div class=\"pointer-events-none absolute end-1.5 top-1 z-2 md:end-2 md:top-1\"><\/div>\n<div class=\"relative\">\n<div class=\"pe-11 pt-3\">\n<div class=\"relative z-0 flex max-w-full\">\n<div id=\"code-block-viewer\" dir=\"ltr\" class=\"q9tKkq_viewer cm-editor z-10 light:cm-light dark:cm-light flex h-full w-full flex-col items-stretch \u037cd \u037cr\">\n<div class=\"cm-scroller\">\n<pre class=\"cm-content q9tKkq_readonly m-0\"><code><span>src\/main\/java<\/span>\n<span> \u251c\u2500\u2500 command<\/span>\n<span> \u2502    \u251c\u2500\u2500 controller<\/span>\n<span> \u2502    \u251c\u2500\u2500 service<\/span>\n<span> \u2502    \u251c\u2500\u2500 aggregate<\/span>\n<span> \u2502    \u251c\u2500\u2500 event<\/span>\n<span> \u2502    \u2514\u2500\u2500 repository<\/span>\n<span> \u2502<\/span>\n<span> \u251c\u2500\u2500 query<\/span>\n<span> \u2502    \u251c\u2500\u2500 controller<\/span>\n<span> \u2502    \u251c\u2500\u2500 projection<\/span>\n<span> \u2502    \u251c\u2500\u2500 repository<\/span>\n<span> \u2502    \u2514\u2500\u2500 service<\/span>\n<span> \u2502<\/span>\n<span> \u2514\u2500\u2500 common<\/span><\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"\">\n<div class=\"\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<hr data-start=\"3569\" data-end=\"3572\" \/>\n<h1 data-section-id=\"y53zvl\" data-start=\"3574\" data-end=\"3606\">Step 1: Creating Domain Events<\/h1>\n<p data-start=\"3608\" data-end=\"3676\">Domain events represent immutable facts that occurred in the system.<\/p>\n<h2 data-section-id=\"7typmw\" data-start=\"3678\" data-end=\"3700\">AccountCreatedEvent<\/h2>\n<div class=\"relative w-full mt-4 mb-1\">\n<div class=\"\">\n<div class=\"relative\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"border border-token-border-light border-radius-3xl corner-superellipse\/1.1 rounded-3xl\">\n<div class=\"h-full w-full border-radius-3xl bg-token-bg-elevated-secondary corner-superellipse\/1.1 overflow-clip rounded-3xl lxnfua_clipPathFallback\">\n<div class=\"pointer-events-none absolute inset-x-4 top-12 bottom-4\">\n<div class=\"pointer-events-none sticky z-40 shrink-0 z-1!\">\n<div class=\"sticky bg-token-border-light\"><\/div>\n<\/div>\n<\/div>\n<div class=\"relative\">\n<div class=\"\">\n<div class=\"relative z-0 flex max-w-full\">\n<div id=\"code-block-viewer\" dir=\"ltr\" class=\"q9tKkq_viewer cm-editor z-10 light:cm-light dark:cm-light flex h-full w-full flex-col items-stretch \u037cd \u037cr\">\n<div class=\"cm-scroller\">\n<pre class=\"cm-content q9tKkq_readonly m-0\"><code><span>@<\/span><span class=\"\u037cm\">Getter<\/span>\n<span>@<\/span><span class=\"\u037cm\">AllArgsConstructor<\/span>\n<span class=\"\u037cg\">public<\/span><span> <\/span><span class=\"\u037cg\">class<\/span><span> <\/span><span class=\"\u037cm\">AccountCreatedEvent<\/span><span> {<\/span>\n\n<span>    <\/span><span class=\"\u037cg\">private<\/span><span> <\/span><span class=\"\u037cg\">final<\/span><span> <\/span><span class=\"\u037cm\">String<\/span><span> <\/span><span class=\"\u037cm\">accountId<\/span><span>;<\/span>\n<span>    <\/span><span class=\"\u037cg\">private<\/span><span> <\/span><span class=\"\u037cg\">final<\/span><span> <\/span><span class=\"\u037cm\">String<\/span><span> <\/span><span class=\"\u037cm\">holderName<\/span><span>;<\/span>\n<span>    <\/span><span class=\"\u037cg\">private<\/span><span> <\/span><span class=\"\u037cg\">final<\/span><span> <\/span><span class=\"\u037cm\">Double<\/span><span> <\/span><span class=\"\u037cm\">initialBalance<\/span><span>;<\/span>\n<span>}<\/span><\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"\">\n<div class=\"\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h2 data-section-id=\"1baclyg\" data-start=\"3895\" data-end=\"3917\">MoneyDepositedEvent<\/h2>\n<div class=\"relative w-full mt-4 mb-1\">\n<div class=\"\">\n<div class=\"relative\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"border border-token-border-light border-radius-3xl corner-superellipse\/1.1 rounded-3xl\">\n<div class=\"h-full w-full border-radius-3xl bg-token-bg-elevated-secondary corner-superellipse\/1.1 overflow-clip rounded-3xl lxnfua_clipPathFallback\">\n<div class=\"pointer-events-none absolute inset-x-4 top-12 bottom-4\">\n<div class=\"pointer-events-none sticky z-40 shrink-0 z-1!\">\n<div class=\"sticky bg-token-border-light\"><\/div>\n<\/div>\n<\/div>\n<div class=\"relative\">\n<div class=\"\">\n<div class=\"relative z-0 flex max-w-full\">\n<div id=\"code-block-viewer\" dir=\"ltr\" class=\"q9tKkq_viewer cm-editor z-10 light:cm-light dark:cm-light flex h-full w-full flex-col items-stretch \u037cd \u037cr\">\n<div class=\"cm-scroller\">\n<pre class=\"cm-content q9tKkq_readonly m-0\"><code><span>@<\/span><span class=\"\u037cm\">Getter<\/span>\n<span>@<\/span><span class=\"\u037cm\">AllArgsConstructor<\/span>\n<span class=\"\u037cg\">public<\/span><span> <\/span><span class=\"\u037cg\">class<\/span><span> <\/span><span class=\"\u037cm\">MoneyDepositedEvent<\/span><span> {<\/span>\n\n<span>    <\/span><span class=\"\u037cg\">private<\/span><span> <\/span><span class=\"\u037cg\">final<\/span><span> <\/span><span class=\"\u037cm\">String<\/span><span> <\/span><span class=\"\u037cm\">accountId<\/span><span>;<\/span>\n<span>    <\/span><span class=\"\u037cg\">private<\/span><span> <\/span><span class=\"\u037cg\">final<\/span><span> <\/span><span class=\"\u037cm\">Double<\/span><span> <\/span><span class=\"\u037cm\">amount<\/span><span>;<\/span>\n<span>}<\/span><\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"\">\n<div class=\"\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<hr data-start=\"4067\" data-end=\"4070\" \/>\n<h1 data-section-id=\"86ul49\" data-start=\"4072\" data-end=\"4099\">Step 2: Creating Commands<\/h1>\n<p data-start=\"4101\" data-end=\"4136\">Commands represent user intentions.<\/p>\n<h2 data-section-id=\"7banhj\" data-start=\"4138\" data-end=\"4161\">CreateAccountCommand<\/h2>\n<div class=\"relative w-full mt-4 mb-1\">\n<div class=\"\">\n<div class=\"relative\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"border border-token-border-light border-radius-3xl corner-superellipse\/1.1 rounded-3xl\">\n<div class=\"h-full w-full border-radius-3xl bg-token-bg-elevated-secondary corner-superellipse\/1.1 overflow-clip rounded-3xl lxnfua_clipPathFallback\">\n<div class=\"pointer-events-none absolute inset-x-4 top-12 bottom-4\">\n<div class=\"pointer-events-none sticky z-40 shrink-0 z-1!\">\n<div class=\"sticky bg-token-border-light\"><\/div>\n<\/div>\n<\/div>\n<div class=\"relative\">\n<div class=\"\">\n<div class=\"relative z-0 flex max-w-full\">\n<div id=\"code-block-viewer\" dir=\"ltr\" class=\"q9tKkq_viewer cm-editor z-10 light:cm-light dark:cm-light flex h-full w-full flex-col items-stretch \u037cd \u037cr\">\n<div class=\"cm-scroller\">\n<pre class=\"cm-content q9tKkq_readonly m-0\"><code><span>@<\/span><span class=\"\u037cm\">Getter<\/span>\n<span>@<\/span><span class=\"\u037cm\">AllArgsConstructor<\/span>\n<span class=\"\u037cg\">public<\/span><span> <\/span><span class=\"\u037cg\">class<\/span><span> <\/span><span class=\"\u037cm\">CreateAccountCommand<\/span><span> {<\/span>\n\n<span>    <\/span><span class=\"\u037cg\">private<\/span><span> <\/span><span class=\"\u037cg\">final<\/span><span> <\/span><span class=\"\u037cm\">String<\/span><span> <\/span><span class=\"\u037cm\">holderName<\/span><span>;<\/span>\n<span>    <\/span><span class=\"\u037cg\">private<\/span><span> <\/span><span class=\"\u037cg\">final<\/span><span> <\/span><span class=\"\u037cm\">Double<\/span><span> <\/span><span class=\"\u037cm\">initialBalance<\/span><span>;<\/span>\n<span>}<\/span><\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"\">\n<div class=\"\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<hr data-start=\"4321\" data-end=\"4324\" \/>\n<h1 data-section-id=\"m9jafr\" data-start=\"4326\" data-end=\"4359\">Step 3: Designing the Aggregate<\/h1>\n<p data-start=\"4361\" data-end=\"4417\">Aggregates contain domain logic and enforce consistency.<\/p>\n<h2 data-section-id=\"1pzw8f7\" data-start=\"4419\" data-end=\"4442\">BankAccountAggregate<\/h2>\n<div class=\"relative w-full mt-4 mb-1\">\n<div class=\"\">\n<div class=\"relative\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"border border-token-border-light border-radius-3xl corner-superellipse\/1.1 rounded-3xl\">\n<div class=\"h-full w-full border-radius-3xl bg-token-bg-elevated-secondary corner-superellipse\/1.1 overflow-clip rounded-3xl lxnfua_clipPathFallback\">\n<div class=\"pointer-events-none absolute inset-x-4 top-12 bottom-4\">\n<div class=\"pointer-events-none sticky z-40 shrink-0 z-1!\">\n<div class=\"sticky bg-token-border-light\"><\/div>\n<\/div>\n<\/div>\n<div class=\"relative\">\n<div class=\"\">\n<div class=\"relative z-0 flex max-w-full\">\n<div id=\"code-block-viewer\" dir=\"ltr\" class=\"q9tKkq_viewer cm-editor z-10 light:cm-light dark:cm-light flex h-full w-full flex-col items-stretch \u037cd \u037cr\">\n<div class=\"cm-scroller\">\n<pre class=\"cm-content q9tKkq_readonly m-0\"><code><span class=\"\u037cg\">public<\/span><span> <\/span><span class=\"\u037cg\">class<\/span><span> <\/span><span class=\"\u037cm\">BankAccountAggregate<\/span><span> {<\/span>\n\n<span>    <\/span><span class=\"\u037cg\">private<\/span><span> <\/span><span class=\"\u037cm\">String<\/span><span> <\/span><span class=\"\u037cm\">accountId<\/span><span>;<\/span>\n<span>    <\/span><span class=\"\u037cg\">private<\/span><span> <\/span><span class=\"\u037cm\">Double<\/span><span> <\/span><span class=\"\u037cm\">balance<\/span><span>;<\/span>\n\n<span>    <\/span><span class=\"\u037cg\">public<\/span><span> <\/span><span class=\"\u037cm\">List<\/span><span>&lt;<\/span><span class=\"\u037cm\">Object<\/span><span>&gt; <\/span><span class=\"\u037cm\">handle<\/span><span>(<\/span><span class=\"\u037cm\">CreateAccountCommand<\/span><span> <\/span><span class=\"\u037cm\">command<\/span><span>) {<\/span>\n\n<span>        <\/span><span class=\"\u037cm\">List<\/span><span>&lt;<\/span><span class=\"\u037cm\">Object<\/span><span>&gt; <\/span><span class=\"\u037cm\">events<\/span><span> <\/span><span class=\"\u037cg\">=<\/span><span> <\/span><span class=\"\u037cg\">new<\/span><span> <\/span><span class=\"\u037cm\">ArrayList<\/span><span>&lt;&gt;();<\/span>\n\n<span>        <\/span><span class=\"\u037cm\">events<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">add<\/span><span>(<\/span>\n<span>            <\/span><span class=\"\u037cg\">new<\/span><span> <\/span><span class=\"\u037cm\">AccountCreatedEvent<\/span><span>(<\/span>\n<span>                <\/span><span class=\"\u037cm\">UUID<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">randomUUID<\/span><span>()<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">toString<\/span><span>(),<\/span>\n<span>                <\/span><span class=\"\u037cm\">command<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">getHolderName<\/span><span>(),<\/span>\n<span>                <\/span><span class=\"\u037cm\">command<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">getInitialBalance<\/span><span>()<\/span>\n<span>            )<\/span>\n<span>        );<\/span>\n\n<span>        <\/span><span class=\"\u037cg\">return<\/span><span> <\/span><span class=\"\u037cm\">events<\/span><span>;<\/span>\n<span>    }<\/span>\n\n<span>    <\/span><span class=\"\u037cg\">public<\/span><span> <\/span><span class=\"\u037cg\">void<\/span><span> <\/span><span class=\"\u037cm\">apply<\/span><span>(<\/span><span class=\"\u037cm\">AccountCreatedEvent<\/span><span> <\/span><span class=\"\u037cm\">event<\/span><span>) {<\/span>\n<span>        <\/span><span class=\"\u037cj\">this<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">accountId<\/span><span> <\/span><span class=\"\u037cg\">=<\/span><span> <\/span><span class=\"\u037cm\">event<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">getAccountId<\/span><span>();<\/span>\n<span>        <\/span><span class=\"\u037cj\">this<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">balance<\/span><span> <\/span><span class=\"\u037cg\">=<\/span><span> <\/span><span class=\"\u037cm\">event<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">getInitialBalance<\/span><span>();<\/span>\n<span>    }<\/span>\n\n<span>    <\/span><span class=\"\u037cg\">public<\/span><span> <\/span><span class=\"\u037cg\">void<\/span><span> <\/span><span class=\"\u037cm\">apply<\/span><span>(<\/span><span class=\"\u037cm\">MoneyDepositedEvent<\/span><span> <\/span><span class=\"\u037cm\">event<\/span><span>) {<\/span>\n<span>        <\/span><span class=\"\u037cj\">this<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">balance<\/span><span> <\/span><span class=\"\u037cg\">+=<\/span><span> <\/span><span class=\"\u037cm\">event<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">getAmount<\/span><span>();<\/span>\n<span>    }<\/span>\n<span>}<\/span><\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"\">\n<div class=\"\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<hr data-start=\"5168\" data-end=\"5171\" \/>\n<h1 data-section-id=\"lv8qor\" data-start=\"5173\" data-end=\"5201\">Step 4: Event Store Design<\/h1>\n<p data-start=\"5203\" data-end=\"5248\">The event store persists events sequentially.<\/p>\n<h2 data-section-id=\"1bvmpsi\" data-start=\"5250\" data-end=\"5265\">Event Entity<\/h2>\n<div class=\"relative w-full mt-4 mb-1\">\n<div class=\"\">\n<div class=\"relative\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"border border-token-border-light border-radius-3xl corner-superellipse\/1.1 rounded-3xl\">\n<div class=\"h-full w-full border-radius-3xl bg-token-bg-elevated-secondary corner-superellipse\/1.1 overflow-clip rounded-3xl lxnfua_clipPathFallback\">\n<div class=\"pointer-events-none absolute inset-x-4 top-12 bottom-4\">\n<div class=\"pointer-events-none sticky z-40 shrink-0 z-1!\">\n<div class=\"sticky bg-token-border-light\"><\/div>\n<\/div>\n<\/div>\n<div class=\"relative\">\n<div class=\"\">\n<div class=\"relative z-0 flex max-w-full\">\n<div id=\"code-block-viewer\" dir=\"ltr\" class=\"q9tKkq_viewer cm-editor z-10 light:cm-light dark:cm-light flex h-full w-full flex-col items-stretch \u037cd \u037cr\">\n<div class=\"cm-scroller\">\n<pre class=\"cm-content q9tKkq_readonly m-0\"><code><span>@<\/span><span class=\"\u037cm\">Entity<\/span>\n<span>@<\/span><span class=\"\u037cm\">Table<\/span><span>(<\/span><span class=\"\u037cm\">name<\/span><span> <\/span><span class=\"\u037cg\">=<\/span><span> <\/span><span class=\"\u037ck\">\"event_store\"<\/span><span>)<\/span>\n<span class=\"\u037cg\">public<\/span><span> <\/span><span class=\"\u037cg\">class<\/span><span> <\/span><span class=\"\u037cm\">EventStoreEntity<\/span><span> {<\/span>\n\n<span>    @<\/span><span class=\"\u037cm\">Id<\/span>\n<span>    @<\/span><span class=\"\u037cm\">GeneratedValue<\/span><span>(<\/span><span class=\"\u037cm\">strategy<\/span><span> <\/span><span class=\"\u037cg\">=<\/span><span> <\/span><span class=\"\u037cm\">GenerationType<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">IDENTITY<\/span><span>)<\/span>\n<span>    <\/span><span class=\"\u037cg\">private<\/span><span> <\/span><span class=\"\u037cm\">Long<\/span><span> <\/span><span class=\"\u037cm\">id<\/span><span>;<\/span>\n\n<span>    <\/span><span class=\"\u037cg\">private<\/span><span> <\/span><span class=\"\u037cm\">String<\/span><span> <\/span><span class=\"\u037cm\">aggregateId<\/span><span>;<\/span>\n\n<span>    <\/span><span class=\"\u037cg\">private<\/span><span> <\/span><span class=\"\u037cm\">String<\/span><span> <\/span><span class=\"\u037cm\">eventType<\/span><span>;<\/span>\n\n<span>    @<\/span><span class=\"\u037cm\">Lob<\/span>\n<span>    <\/span><span class=\"\u037cg\">private<\/span><span> <\/span><span class=\"\u037cm\">String<\/span><span> <\/span><span class=\"\u037cm\">eventData<\/span><span>;<\/span>\n\n<span>    <\/span><span class=\"\u037cg\">private<\/span><span> <\/span><span class=\"\u037cm\">LocalDateTime<\/span><span> <\/span><span class=\"\u037cm\">createdAt<\/span><span>;<\/span>\n<span>}<\/span><\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"\">\n<div class=\"\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<hr data-start=\"5579\" data-end=\"5582\" \/>\n<h1 data-section-id=\"1kce27y\" data-start=\"5584\" data-end=\"5611\">Step 5: Persisting Events<\/h1>\n<h2 data-section-id=\"17zhrf8\" data-start=\"5613\" data-end=\"5638\">Event Store Repository<\/h2>\n<div class=\"relative w-full mt-4 mb-1\">\n<div class=\"\">\n<div class=\"relative\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"border border-token-border-light border-radius-3xl corner-superellipse\/1.1 rounded-3xl\">\n<div class=\"h-full w-full border-radius-3xl bg-token-bg-elevated-secondary corner-superellipse\/1.1 overflow-clip rounded-3xl lxnfua_clipPathFallback\">\n<div class=\"pointer-events-none absolute inset-x-4 top-12 bottom-4\">\n<div class=\"pointer-events-none sticky z-40 shrink-0 z-1!\">\n<div class=\"sticky bg-token-border-light\"><\/div>\n<\/div>\n<\/div>\n<div class=\"relative\">\n<div class=\"\">\n<div class=\"relative z-0 flex max-w-full\">\n<div id=\"code-block-viewer\" dir=\"ltr\" class=\"q9tKkq_viewer cm-editor z-10 light:cm-light dark:cm-light flex h-full w-full flex-col items-stretch \u037cd \u037cr\">\n<div class=\"cm-scroller\">\n<pre class=\"cm-content q9tKkq_readonly m-0\"><code><span>@<\/span><span class=\"\u037cm\">Repository<\/span>\n<span class=\"\u037cg\">public<\/span><span> <\/span><span class=\"\u037cg\">interface<\/span><span> <\/span><span class=\"\u037cm\">EventStoreRepository<\/span>\n<span>        <\/span><span class=\"\u037cg\">extends<\/span><span> <\/span><span class=\"\u037cm\">JpaRepository<\/span><span>&lt;<\/span><span class=\"\u037cm\">EventStoreEntity<\/span><span>, <\/span><span class=\"\u037cm\">Long<\/span><span>&gt; {<\/span>\n<span>}<\/span><\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"\">\n<div class=\"\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h2 data-section-id=\"14i5iiz\" data-start=\"5761\" data-end=\"5783\">Event Store Service<\/h2>\n<div class=\"relative w-full mt-4 mb-1\">\n<div class=\"\">\n<div class=\"relative\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"border border-token-border-light border-radius-3xl corner-superellipse\/1.1 rounded-3xl\">\n<div class=\"h-full w-full border-radius-3xl bg-token-bg-elevated-secondary corner-superellipse\/1.1 overflow-clip rounded-3xl lxnfua_clipPathFallback\">\n<div class=\"pointer-events-none absolute inset-x-4 top-12 bottom-4\">\n<div class=\"pointer-events-none sticky z-40 shrink-0 z-1!\">\n<div class=\"sticky bg-token-border-light\"><\/div>\n<\/div>\n<\/div>\n<div class=\"relative\">\n<div class=\"\">\n<div class=\"relative z-0 flex max-w-full\">\n<div id=\"code-block-viewer\" dir=\"ltr\" class=\"q9tKkq_viewer cm-editor z-10 light:cm-light dark:cm-light flex h-full w-full flex-col items-stretch \u037cd \u037cr\">\n<div class=\"cm-scroller\">\n<pre class=\"cm-content q9tKkq_readonly m-0\"><code><span>@<\/span><span class=\"\u037cm\">Service<\/span>\n<span>@<\/span><span class=\"\u037cm\">RequiredArgsConstructor<\/span>\n<span class=\"\u037cg\">public<\/span><span> <\/span><span class=\"\u037cg\">class<\/span><span> <\/span><span class=\"\u037cm\">EventStoreService<\/span><span> {<\/span>\n\n<span>    <\/span><span class=\"\u037cg\">private<\/span><span> <\/span><span class=\"\u037cg\">final<\/span><span> <\/span><span class=\"\u037cm\">EventStoreRepository<\/span><span> <\/span><span class=\"\u037cm\">repository<\/span><span>;<\/span>\n<span>    <\/span><span class=\"\u037cg\">private<\/span><span> <\/span><span class=\"\u037cg\">final<\/span><span> <\/span><span class=\"\u037cm\">ObjectMapper<\/span><span> <\/span><span class=\"\u037cm\">objectMapper<\/span><span>;<\/span>\n\n<span>    <\/span><span class=\"\u037cg\">public<\/span><span> <\/span><span class=\"\u037cg\">void<\/span><span> <\/span><span class=\"\u037cm\">saveEvent<\/span><span>(<\/span>\n<span>            <\/span><span class=\"\u037cm\">String<\/span><span> <\/span><span class=\"\u037cm\">aggregateId<\/span><span>,<\/span>\n<span>            <\/span><span class=\"\u037cm\">Object<\/span><span> <\/span><span class=\"\u037cm\">event<\/span><span>) <\/span><span class=\"\u037cg\">throws<\/span><span> <\/span><span class=\"\u037cm\">Exception<\/span><span> {<\/span>\n\n<span>        <\/span><span class=\"\u037cm\">EventStoreEntity<\/span><span> <\/span><span class=\"\u037cm\">entity<\/span><span> <\/span><span class=\"\u037cg\">=<\/span><span> <\/span><span class=\"\u037cg\">new<\/span><span> <\/span><span class=\"\u037cm\">EventStoreEntity<\/span><span>();<\/span>\n\n<span>        <\/span><span class=\"\u037cm\">entity<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">setAggregateId<\/span><span>(<\/span><span class=\"\u037cm\">aggregateId<\/span><span>);<\/span>\n<span>        <\/span><span class=\"\u037cm\">entity<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">setEventType<\/span><span>(<\/span><span class=\"\u037cm\">event<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">getClass<\/span><span>()<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">getName<\/span><span>());<\/span>\n<span>        <\/span><span class=\"\u037cm\">entity<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">setEventData<\/span><span>(<\/span>\n<span>                <\/span><span class=\"\u037cm\">objectMapper<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">writeValueAsString<\/span><span>(<\/span><span class=\"\u037cm\">event<\/span><span>));<\/span>\n<span>        <\/span><span class=\"\u037cm\">entity<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">setCreatedAt<\/span><span>(<\/span><span class=\"\u037cm\">LocalDateTime<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">now<\/span><span>());<\/span>\n\n<span>        <\/span><span class=\"\u037cm\">repository<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">save<\/span><span>(<\/span><span class=\"\u037cm\">entity<\/span><span>);<\/span>\n<span>    }<\/span>\n<span>}<\/span><\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"\">\n<div class=\"\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<hr data-start=\"6406\" data-end=\"6409\" \/>\n<h1 data-section-id=\"1f35bbu\" data-start=\"6411\" data-end=\"6449\">Step 6: Publishing Events with Kafka<\/h1>\n<p data-start=\"6451\" data-end=\"6504\">After persisting events, publish them asynchronously.<\/p>\n<h2 data-section-id=\"1tg7yiz\" data-start=\"6506\" data-end=\"6523\">Kafka Producer<\/h2>\n<div class=\"relative w-full mt-4 mb-1\">\n<div class=\"\">\n<div class=\"relative\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"border border-token-border-light border-radius-3xl corner-superellipse\/1.1 rounded-3xl\">\n<div class=\"h-full w-full border-radius-3xl bg-token-bg-elevated-secondary corner-superellipse\/1.1 overflow-clip rounded-3xl lxnfua_clipPathFallback\">\n<div class=\"pointer-events-none absolute inset-x-4 top-12 bottom-4\">\n<div class=\"pointer-events-none sticky z-40 shrink-0 z-1!\">\n<div class=\"sticky bg-token-border-light\"><\/div>\n<\/div>\n<\/div>\n<div class=\"relative\">\n<div class=\"\">\n<div class=\"relative z-0 flex max-w-full\">\n<div id=\"code-block-viewer\" dir=\"ltr\" class=\"q9tKkq_viewer cm-editor z-10 light:cm-light dark:cm-light flex h-full w-full flex-col items-stretch \u037cd \u037cr\">\n<div class=\"cm-scroller\">\n<pre class=\"cm-content q9tKkq_readonly m-0\"><code><span>@<\/span><span class=\"\u037cm\">Service<\/span>\n<span>@<\/span><span class=\"\u037cm\">RequiredArgsConstructor<\/span>\n<span class=\"\u037cg\">public<\/span><span> <\/span><span class=\"\u037cg\">class<\/span><span> <\/span><span class=\"\u037cm\">EventPublisher<\/span><span> {<\/span>\n\n<span>    <\/span><span class=\"\u037cg\">private<\/span><span> <\/span><span class=\"\u037cg\">final<\/span><span> <\/span><span class=\"\u037cm\">KafkaTemplate<\/span><span>&lt;<\/span><span class=\"\u037cm\">String<\/span><span>, <\/span><span class=\"\u037cm\">Object<\/span><span>&gt; <\/span><span class=\"\u037cm\">kafkaTemplate<\/span><span>;<\/span>\n\n<span>    <\/span><span class=\"\u037cg\">public<\/span><span> <\/span><span class=\"\u037cg\">void<\/span><span> <\/span><span class=\"\u037cm\">publish<\/span><span>(<\/span><span class=\"\u037cm\">Object<\/span><span> <\/span><span class=\"\u037cm\">event<\/span><span>) {<\/span>\n\n<span>        <\/span><span class=\"\u037cm\">kafkaTemplate<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">send<\/span><span>(<\/span>\n<span>            <\/span><span class=\"\u037ck\">\"bank-events\"<\/span><span>,<\/span>\n<span>            <\/span><span class=\"\u037cm\">event<\/span>\n<span>        );<\/span>\n<span>    }<\/span>\n<span>}<\/span><\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"\">\n<div class=\"\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<hr data-start=\"6800\" data-end=\"6803\" \/>\n<h1 data-section-id=\"lgwi4j\" data-start=\"6805\" data-end=\"6830\">Step 7: Command Service<\/h1>\n<p data-start=\"6832\" data-end=\"6877\">The command service handles write operations.<\/p>\n<div class=\"relative w-full mt-4 mb-1\">\n<div class=\"\">\n<div class=\"relative\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"border border-token-border-light border-radius-3xl corner-superellipse\/1.1 rounded-3xl\">\n<div class=\"h-full w-full border-radius-3xl bg-token-bg-elevated-secondary corner-superellipse\/1.1 overflow-clip rounded-3xl lxnfua_clipPathFallback\">\n<div class=\"pointer-events-none absolute inset-x-4 top-12 bottom-4\">\n<div class=\"pointer-events-none sticky z-40 shrink-0 z-1!\">\n<div class=\"sticky bg-token-border-light\"><\/div>\n<\/div>\n<\/div>\n<div class=\"relative\">\n<div class=\"\">\n<div class=\"relative z-0 flex max-w-full\">\n<div id=\"code-block-viewer\" dir=\"ltr\" class=\"q9tKkq_viewer cm-editor z-10 light:cm-light dark:cm-light flex h-full w-full flex-col items-stretch \u037cd \u037cr\">\n<div class=\"cm-scroller\">\n<pre class=\"cm-content q9tKkq_readonly m-0\"><code><span>@<\/span><span class=\"\u037cm\">Service<\/span>\n<span>@<\/span><span class=\"\u037cm\">RequiredArgsConstructor<\/span>\n<span class=\"\u037cg\">public<\/span><span> <\/span><span class=\"\u037cg\">class<\/span><span> <\/span><span class=\"\u037cm\">AccountCommandService<\/span><span> {<\/span>\n\n<span>    <\/span><span class=\"\u037cg\">private<\/span><span> <\/span><span class=\"\u037cg\">final<\/span><span> <\/span><span class=\"\u037cm\">EventStoreService<\/span><span> <\/span><span class=\"\u037cm\">eventStoreService<\/span><span>;<\/span>\n<span>    <\/span><span class=\"\u037cg\">private<\/span><span> <\/span><span class=\"\u037cg\">final<\/span><span> <\/span><span class=\"\u037cm\">EventPublisher<\/span><span> <\/span><span class=\"\u037cm\">publisher<\/span><span>;<\/span>\n\n<span>    <\/span><span class=\"\u037cg\">public<\/span><span> <\/span><span class=\"\u037cg\">void<\/span><span> <\/span><span class=\"\u037cm\">createAccount<\/span><span>(<\/span>\n<span>            <\/span><span class=\"\u037cm\">CreateAccountCommand<\/span><span> <\/span><span class=\"\u037cm\">command<\/span><span>)<\/span>\n<span>            <\/span><span class=\"\u037cg\">throws<\/span><span> <\/span><span class=\"\u037cm\">Exception<\/span><span> {<\/span>\n\n<span>        <\/span><span class=\"\u037cm\">BankAccountAggregate<\/span><span> <\/span><span class=\"\u037cm\">aggregate<\/span><span> <\/span><span class=\"\u037cg\">=<\/span>\n<span>                <\/span><span class=\"\u037cg\">new<\/span><span> <\/span><span class=\"\u037cm\">BankAccountAggregate<\/span><span>();<\/span>\n\n<span>        <\/span><span class=\"\u037cm\">List<\/span><span>&lt;<\/span><span class=\"\u037cm\">Object<\/span><span>&gt; <\/span><span class=\"\u037cm\">events<\/span><span> <\/span><span class=\"\u037cg\">=<\/span>\n<span>                <\/span><span class=\"\u037cm\">aggregate<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">handle<\/span><span>(<\/span><span class=\"\u037cm\">command<\/span><span>);<\/span>\n\n<span>        <\/span><span class=\"\u037cg\">for<\/span><span> (<\/span><span class=\"\u037cm\">Object<\/span><span> <\/span><span class=\"\u037cm\">event<\/span><span> : <\/span><span class=\"\u037cm\">events<\/span><span>) {<\/span>\n\n<span>            <\/span><span class=\"\u037cm\">eventStoreService<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">saveEvent<\/span><span>(<\/span>\n<span>                    <\/span><span class=\"\u037cm\">UUID<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">randomUUID<\/span><span>()<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">toString<\/span><span>(),<\/span>\n<span>                    <\/span><span class=\"\u037cm\">event<\/span>\n<span>            );<\/span>\n\n<span>            <\/span><span class=\"\u037cm\">publisher<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">publish<\/span><span>(<\/span><span class=\"\u037cm\">event<\/span><span>);<\/span>\n<span>        }<\/span>\n<span>    }<\/span>\n<span>}<\/span><\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"\">\n<div class=\"\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<hr data-start=\"7557\" data-end=\"7560\" \/>\n<h1 data-section-id=\"semhoz\" data-start=\"7562\" data-end=\"7583\">Step 8: Query Model<\/h1>\n<p data-start=\"7585\" data-end=\"7634\">The query model is optimized for read operations.<\/p>\n<h2 data-section-id=\"fb0ka4\" data-start=\"7636\" data-end=\"7650\">Read Entity<\/h2>\n<div class=\"relative w-full mt-4 mb-1\">\n<div class=\"\">\n<div class=\"relative\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"border border-token-border-light border-radius-3xl corner-superellipse\/1.1 rounded-3xl\">\n<div class=\"h-full w-full border-radius-3xl bg-token-bg-elevated-secondary corner-superellipse\/1.1 overflow-clip rounded-3xl lxnfua_clipPathFallback\">\n<div class=\"pointer-events-none absolute inset-x-4 top-12 bottom-4\">\n<div class=\"pointer-events-none sticky z-40 shrink-0 z-1!\">\n<div class=\"sticky bg-token-border-light\"><\/div>\n<\/div>\n<\/div>\n<div class=\"relative\">\n<div class=\"\">\n<div class=\"relative z-0 flex max-w-full\">\n<div id=\"code-block-viewer\" dir=\"ltr\" class=\"q9tKkq_viewer cm-editor z-10 light:cm-light dark:cm-light flex h-full w-full flex-col items-stretch \u037cd \u037cr\">\n<div class=\"cm-scroller\">\n<pre class=\"cm-content q9tKkq_readonly m-0\"><code><span>@<\/span><span class=\"\u037cm\">Entity<\/span>\n<span>@<\/span><span class=\"\u037cm\">Table<\/span><span>(<\/span><span class=\"\u037cm\">name<\/span><span> <\/span><span class=\"\u037cg\">=<\/span><span> <\/span><span class=\"\u037ck\">\"account_view\"<\/span><span>)<\/span>\n<span class=\"\u037cg\">public<\/span><span> <\/span><span class=\"\u037cg\">class<\/span><span> <\/span><span class=\"\u037cm\">AccountView<\/span><span> {<\/span>\n\n<span>    @<\/span><span class=\"\u037cm\">Id<\/span>\n<span>    <\/span><span class=\"\u037cg\">private<\/span><span> <\/span><span class=\"\u037cm\">String<\/span><span> <\/span><span class=\"\u037cm\">accountId<\/span><span>;<\/span>\n\n<span>    <\/span><span class=\"\u037cg\">private<\/span><span> <\/span><span class=\"\u037cm\">String<\/span><span> <\/span><span class=\"\u037cm\">holderName<\/span><span>;<\/span>\n\n<span>    <\/span><span class=\"\u037cg\">private<\/span><span> <\/span><span class=\"\u037cm\">Double<\/span><span> <\/span><span class=\"\u037cm\">balance<\/span><span>;<\/span>\n<span>}<\/span><\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"\">\n<div class=\"\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<hr data-start=\"7832\" data-end=\"7835\" \/>\n<h1 data-section-id=\"3bm2lu\" data-start=\"7837\" data-end=\"7865\">Step 9: Projection Handler<\/h1>\n<p data-start=\"7867\" data-end=\"7928\">Projection handlers consume events and update the read model.<\/p>\n<div class=\"relative w-full mt-4 mb-1\">\n<div class=\"\">\n<div class=\"relative\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"border border-token-border-light border-radius-3xl corner-superellipse\/1.1 rounded-3xl\">\n<div class=\"h-full w-full border-radius-3xl bg-token-bg-elevated-secondary corner-superellipse\/1.1 overflow-clip rounded-3xl lxnfua_clipPathFallback\">\n<div class=\"pointer-events-none absolute inset-x-4 top-12 bottom-4\">\n<div class=\"pointer-events-none sticky z-40 shrink-0 z-1!\">\n<div class=\"sticky bg-token-border-light\"><\/div>\n<\/div>\n<\/div>\n<div class=\"relative\">\n<div class=\"\">\n<div class=\"relative z-0 flex max-w-full\">\n<div id=\"code-block-viewer\" dir=\"ltr\" class=\"q9tKkq_viewer cm-editor z-10 light:cm-light dark:cm-light flex h-full w-full flex-col items-stretch \u037cd \u037cr\">\n<div class=\"cm-scroller\">\n<pre class=\"cm-content q9tKkq_readonly m-0\"><code><span>@<\/span><span class=\"\u037cm\">Component<\/span>\n<span>@<\/span><span class=\"\u037cm\">RequiredArgsConstructor<\/span>\n<span class=\"\u037cg\">public<\/span><span> <\/span><span class=\"\u037cg\">class<\/span><span> <\/span><span class=\"\u037cm\">AccountProjection<\/span><span> {<\/span>\n\n<span>    <\/span><span class=\"\u037cg\">private<\/span><span> <\/span><span class=\"\u037cg\">final<\/span><span> <\/span><span class=\"\u037cm\">AccountViewRepository<\/span><span> <\/span><span class=\"\u037cm\">repository<\/span><span>;<\/span>\n\n<span>    @<\/span><span class=\"\u037cm\">KafkaListener<\/span><span>(<\/span>\n<span>        <\/span><span class=\"\u037cm\">topics<\/span><span> <\/span><span class=\"\u037cg\">=<\/span><span> <\/span><span class=\"\u037ck\">\"bank-events\"<\/span><span>,<\/span>\n<span>        <\/span><span class=\"\u037cm\">groupId<\/span><span> <\/span><span class=\"\u037cg\">=<\/span><span> <\/span><span class=\"\u037ck\">\"query-group\"<\/span>\n<span>    )<\/span>\n<span>    <\/span><span class=\"\u037cg\">public<\/span><span> <\/span><span class=\"\u037cg\">void<\/span><span> <\/span><span class=\"\u037cm\">consume<\/span><span>(<\/span><span class=\"\u037cm\">AccountCreatedEvent<\/span><span> <\/span><span class=\"\u037cm\">event<\/span><span>) {<\/span>\n\n<span>        <\/span><span class=\"\u037cm\">AccountView<\/span><span> <\/span><span class=\"\u037cm\">view<\/span><span> <\/span><span class=\"\u037cg\">=<\/span><span> <\/span><span class=\"\u037cg\">new<\/span><span> <\/span><span class=\"\u037cm\">AccountView<\/span><span>();<\/span>\n\n<span>        <\/span><span class=\"\u037cm\">view<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">setAccountId<\/span><span>(<\/span><span class=\"\u037cm\">event<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">getAccountId<\/span><span>());<\/span>\n<span>        <\/span><span class=\"\u037cm\">view<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">setHolderName<\/span><span>(<\/span><span class=\"\u037cm\">event<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">getHolderName<\/span><span>());<\/span>\n<span>        <\/span><span class=\"\u037cm\">view<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">setBalance<\/span><span>(<\/span><span class=\"\u037cm\">event<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">getInitialBalance<\/span><span>());<\/span>\n\n<span>        <\/span><span class=\"\u037cm\">repository<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">save<\/span><span>(<\/span><span class=\"\u037cm\">view<\/span><span>);<\/span>\n<span>    }<\/span>\n<span>}<\/span><\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"\">\n<div class=\"\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<hr data-start=\"8449\" data-end=\"8452\" \/>\n<h1 data-section-id=\"1ecla0t\" data-start=\"8454\" data-end=\"8474\">Step 10: Query API<\/h1>\n<div class=\"relative w-full mt-4 mb-1\">\n<div class=\"\">\n<div class=\"relative\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"border border-token-border-light border-radius-3xl corner-superellipse\/1.1 rounded-3xl\">\n<div class=\"h-full w-full border-radius-3xl bg-token-bg-elevated-secondary corner-superellipse\/1.1 overflow-clip rounded-3xl lxnfua_clipPathFallback\">\n<div class=\"pointer-events-none absolute inset-x-4 top-12 bottom-4\">\n<div class=\"pointer-events-none sticky z-40 shrink-0 z-1!\">\n<div class=\"sticky bg-token-border-light\"><\/div>\n<\/div>\n<\/div>\n<div class=\"relative\">\n<div class=\"\">\n<div class=\"relative z-0 flex max-w-full\">\n<div id=\"code-block-viewer\" dir=\"ltr\" class=\"q9tKkq_viewer cm-editor z-10 light:cm-light dark:cm-light flex h-full w-full flex-col items-stretch \u037cd \u037cr\">\n<div class=\"cm-scroller\">\n<pre class=\"cm-content q9tKkq_readonly m-0\"><code><span>@<\/span><span class=\"\u037cm\">RestController<\/span>\n<span>@<\/span><span class=\"\u037cm\">RequiredArgsConstructor<\/span>\n<span>@<\/span><span class=\"\u037cm\">RequestMapping<\/span><span>(<\/span><span class=\"\u037ck\">\"\/accounts\"<\/span><span>)<\/span>\n<span class=\"\u037cg\">public<\/span><span> <\/span><span class=\"\u037cg\">class<\/span><span> <\/span><span class=\"\u037cm\">AccountQueryController<\/span><span> {<\/span>\n\n<span>    <\/span><span class=\"\u037cg\">private<\/span><span> <\/span><span class=\"\u037cg\">final<\/span><span> <\/span><span class=\"\u037cm\">AccountViewRepository<\/span><span> <\/span><span class=\"\u037cm\">repository<\/span><span>;<\/span>\n\n<span>    @<\/span><span class=\"\u037cm\">GetMapping<\/span><span>(<\/span><span class=\"\u037ck\">\"\/{id}\"<\/span><span>)<\/span>\n<span>    <\/span><span class=\"\u037cg\">public<\/span><span> <\/span><span class=\"\u037cm\">AccountView<\/span><span> <\/span><span class=\"\u037cm\">getAccount<\/span><span>(<\/span>\n<span>            @<\/span><span class=\"\u037cm\">PathVariable<\/span><span> <\/span><span class=\"\u037cm\">String<\/span><span> <\/span><span class=\"\u037cm\">id<\/span><span>) {<\/span>\n\n<span>        <\/span><span class=\"\u037cg\">return<\/span><span> <\/span><span class=\"\u037cm\">repository<\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">findById<\/span><span>(<\/span><span class=\"\u037cm\">id<\/span><span>)<\/span>\n<span>                <\/span><span class=\"\u037cg\">.<\/span><span class=\"\u037cm\">orElseThrow<\/span><span>();<\/span>\n<span>    }<\/span>\n<span>}<\/span><\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"\">\n<div class=\"\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<hr data-start=\"8830\" data-end=\"8833\" \/>\n<h1 data-section-id=\"vkdkbm\" data-start=\"8835\" data-end=\"8859\">Event Replay Mechanism<\/h1>\n<p data-start=\"8861\" data-end=\"8930\">One of the biggest advantages of Event Sourcing is replay capability.<\/p>\n<p data-start=\"8932\" data-end=\"8971\">If the read database becomes corrupted:<\/p>\n<ol data-start=\"8973\" data-end=\"9071\">\n<li data-section-id=\"1bfqwea\" data-start=\"8973\" data-end=\"9006\">Delete the projection database<\/li>\n<li data-section-id=\"kyh5cf\" data-start=\"9007\" data-end=\"9034\">Replay all stored events<\/li>\n<li data-section-id=\"1oy9tma\" data-start=\"9035\" data-end=\"9071\">Rebuild projections automatically<\/li>\n<\/ol>\n<p data-start=\"9073\" data-end=\"9120\">This enables resilient and recoverable systems.<\/p>\n<hr data-start=\"9122\" data-end=\"9125\" \/>\n<h1 data-section-id=\"18va99a\" data-start=\"9127\" data-end=\"9141\">Snapshotting<\/h1>\n<p data-start=\"9143\" data-end=\"9194\">Replaying thousands of events can become expensive.<\/p>\n<p data-start=\"9196\" data-end=\"9245\">Snapshotting periodically stores aggregate state.<\/p>\n<p data-start=\"9247\" data-end=\"9255\">Example:<\/p>\n<div class=\"relative w-full mt-4 mb-1\">\n<div class=\"\">\n<div class=\"relative\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"border border-token-border-light border-radius-3xl corner-superellipse\/1.1 rounded-3xl\">\n<div class=\"h-full w-full border-radius-3xl bg-token-bg-elevated-secondary corner-superellipse\/1.1 overflow-clip rounded-3xl lxnfua_clipPathFallback\">\n<div class=\"pointer-events-none absolute end-1.5 top-1 z-2 md:end-2 md:top-1\"><\/div>\n<div class=\"relative\">\n<div class=\"pe-11 pt-3\">\n<div class=\"relative z-0 flex max-w-full\">\n<div id=\"code-block-viewer\" dir=\"ltr\" class=\"q9tKkq_viewer cm-editor z-10 light:cm-light dark:cm-light flex h-full w-full flex-col items-stretch \u037cd \u037cr\">\n<div class=\"cm-scroller\">\n<pre class=\"cm-content q9tKkq_readonly m-0\"><code><span>After every 100 events:<\/span>\n<span>Save current aggregate snapshot<\/span><\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"\">\n<div class=\"\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p data-start=\"9326\" data-end=\"9343\">Benefits include:<\/p>\n<ul data-start=\"9345\" data-end=\"9423\">\n<li data-section-id=\"uiy2ac\" data-start=\"9345\" data-end=\"9378\">Faster aggregate reconstruction<\/li>\n<li data-section-id=\"1y38wbu\" data-start=\"9379\" data-end=\"9400\">Reduced replay time<\/li>\n<li data-section-id=\"dcovwu\" data-start=\"9401\" data-end=\"9423\">Improved performance<\/li>\n<\/ul>\n<hr data-start=\"9425\" data-end=\"9428\" \/>\n<h1 data-section-id=\"e0yu67\" data-start=\"9430\" data-end=\"9457\">Handling Event Versioning<\/h1>\n<p data-start=\"9459\" data-end=\"9484\">Over time, events evolve.<\/p>\n<p data-start=\"9486\" data-end=\"9498\">For example:<\/p>\n<div class=\"relative w-full mt-4 mb-1\">\n<div class=\"\">\n<div class=\"relative\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"border border-token-border-light border-radius-3xl corner-superellipse\/1.1 rounded-3xl\">\n<div class=\"h-full w-full border-radius-3xl bg-token-bg-elevated-secondary corner-superellipse\/1.1 overflow-clip rounded-3xl lxnfua_clipPathFallback\">\n<div class=\"pointer-events-none absolute end-1.5 top-1 z-2 md:end-2 md:top-1\"><\/div>\n<div class=\"relative\">\n<div class=\"pe-11 pt-3\">\n<div class=\"relative z-0 flex max-w-full\">\n<div id=\"code-block-viewer\" dir=\"ltr\" class=\"q9tKkq_viewer cm-editor z-10 light:cm-light dark:cm-light flex h-full w-full flex-col items-stretch \u037cd \u037cr\">\n<div class=\"cm-scroller\">\n<pre class=\"cm-content q9tKkq_readonly m-0\"><code><span>UserCreatedEvent V1<\/span>\n<span>UserCreatedEvent V2<\/span><\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"\">\n<div class=\"\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p data-start=\"9553\" data-end=\"9579\">Strategies for versioning:<\/p>\n<ul data-start=\"9581\" data-end=\"9686\">\n<li data-section-id=\"1q7l6qy\" data-start=\"9581\" data-end=\"9610\">Backward-compatible schemas<\/li>\n<li data-section-id=\"1ljjmcx\" data-start=\"9611\" data-end=\"9642\">Event transformation adapters<\/li>\n<li data-section-id=\"z6v11o\" data-start=\"9643\" data-end=\"9660\">Schema registry<\/li>\n<li data-section-id=\"14yhmiw\" data-start=\"9661\" data-end=\"9686\">Separate event versions<\/li>\n<\/ul>\n<hr data-start=\"9688\" data-end=\"9691\" \/>\n<h1 data-section-id=\"182lecm\" data-start=\"9693\" data-end=\"9715\">Ensuring Idempotency<\/h1>\n<p data-start=\"9717\" data-end=\"9769\">Event consumers must handle duplicate events safely.<\/p>\n<p data-start=\"9771\" data-end=\"9789\">Common approaches:<\/p>\n<ul data-start=\"9791\" data-end=\"9876\">\n<li data-section-id=\"u3uuz3\" data-start=\"9791\" data-end=\"9818\">Store processed event IDs<\/li>\n<li data-section-id=\"1pfx0b2\" data-start=\"9819\" data-end=\"9843\">Use unique constraints<\/li>\n<li data-section-id=\"1md4h04\" data-start=\"9844\" data-end=\"9876\">Design consumers as idempotent<\/li>\n<\/ul>\n<hr data-start=\"9878\" data-end=\"9881\" \/>\n<h1 data-section-id=\"641gqp\" data-start=\"9883\" data-end=\"9910\">Transactional Consistency<\/h1>\n<p data-start=\"9912\" data-end=\"9959\">CQRS systems are usually eventually consistent.<\/p>\n<p data-start=\"9961\" data-end=\"9972\">This means:<\/p>\n<ul data-start=\"9974\" data-end=\"10065\">\n<li data-section-id=\"3eqppa\" data-start=\"9974\" data-end=\"9996\">Writes succeed first<\/li>\n<li data-section-id=\"4xhfa\" data-start=\"9997\" data-end=\"10032\">Read models update asynchronously<\/li>\n<li data-section-id=\"tdvnrj\" data-start=\"10033\" data-end=\"10065\">Temporary read lag is expected<\/li>\n<\/ul>\n<p data-start=\"10067\" data-end=\"10130\">Applications must be designed to tolerate eventual consistency.<\/p>\n<hr data-start=\"10132\" data-end=\"10135\" \/>\n<h1 data-section-id=\"14vxrsr\" data-start=\"10137\" data-end=\"10176\">Advantages of CQRS and Event Sourcing<\/h1>\n<h2 data-section-id=\"1pm7psu\" data-start=\"10178\" data-end=\"10200\">Independent Scaling<\/h2>\n<p data-start=\"10202\" data-end=\"10244\">Read and write workloads scale separately.<\/p>\n<h2 data-section-id=\"1atbns3\" data-start=\"10246\" data-end=\"10269\">Improved Performance<\/h2>\n<p data-start=\"10271\" data-end=\"10317\">Optimized read models reduce query complexity.<\/p>\n<h2 data-section-id=\"1mus2lf\" data-start=\"10319\" data-end=\"10344\">Complete Audit History<\/h2>\n<p data-start=\"10346\" data-end=\"10384\">Every change is preserved permanently.<\/p>\n<h2 data-section-id=\"1fy0k9e\" data-start=\"10386\" data-end=\"10422\">Better Microservice Communication<\/h2>\n<p data-start=\"10424\" data-end=\"10476\">Events integrate naturally with distributed systems.<\/p>\n<h2 data-section-id=\"1hxuo7y\" data-start=\"10478\" data-end=\"10501\">Flexible Read Models<\/h2>\n<p data-start=\"10503\" data-end=\"10560\">Different projections can serve different business needs.<\/p>\n<hr data-start=\"10562\" data-end=\"10565\" \/>\n<h1 data-section-id=\"18zbc22\" data-start=\"10567\" data-end=\"10594\">Challenges and Trade-Offs<\/h1>\n<p data-start=\"10596\" data-end=\"10652\">CQRS and Event Sourcing introduce additional complexity.<\/p>\n<h2 data-section-id=\"1lvj7ua\" data-start=\"10654\" data-end=\"10689\">Increased Development Complexity<\/h2>\n<p data-start=\"10691\" data-end=\"10741\">Developers must understand asynchronous workflows.<\/p>\n<h2 data-section-id=\"2a9q4f\" data-start=\"10743\" data-end=\"10766\">Eventual Consistency<\/h2>\n<p data-start=\"10768\" data-end=\"10813\">Immediate consistency is harder to guarantee.<\/p>\n<h2 data-section-id=\"1wyza9\" data-start=\"10815\" data-end=\"10840\">Event Schema Evolution<\/h2>\n<p data-start=\"10842\" data-end=\"10895\">Maintaining backward compatibility becomes important.<\/p>\n<h2 data-section-id=\"1xr2gs9\" data-start=\"10897\" data-end=\"10922\">Operational Complexity<\/h2>\n<p data-start=\"10924\" data-end=\"10984\">Managing Kafka clusters and event stores requires expertise.<\/p>\n<hr data-start=\"10986\" data-end=\"10989\" \/>\n<h1 data-section-id=\"1az13pz\" data-start=\"10991\" data-end=\"11018\">When Should You Use CQRS?<\/h1>\n<p data-start=\"11020\" data-end=\"11062\">CQRS and Event Sourcing are valuable when:<\/p>\n<ul data-start=\"11064\" data-end=\"11243\">\n<li data-section-id=\"1rcjut4\" data-start=\"11064\" data-end=\"11096\">Business workflows are complex<\/li>\n<li data-section-id=\"j85zzp\" data-start=\"11097\" data-end=\"11125\">Audit trails are mandatory<\/li>\n<li data-section-id=\"1bmst50\" data-start=\"11126\" data-end=\"11155\">Systems are highly scalable<\/li>\n<li data-section-id=\"my7tei\" data-start=\"11156\" data-end=\"11203\">Read and write workloads differ significantly<\/li>\n<li data-section-id=\"glgerx\" data-start=\"11204\" data-end=\"11243\">Event-driven architecture is required<\/li>\n<\/ul>\n<p data-start=\"11245\" data-end=\"11276\">Avoid using these patterns for:<\/p>\n<ul data-start=\"11278\" data-end=\"11365\">\n<li data-section-id=\"jbjie6\" data-start=\"11278\" data-end=\"11303\">Small CRUD applications<\/li>\n<li data-section-id=\"17w1kcu\" data-start=\"11304\" data-end=\"11326\">Simple admin portals<\/li>\n<li data-section-id=\"1flpr1b\" data-start=\"11327\" data-end=\"11346\">Low-scale systems<\/li>\n<li data-section-id=\"26w4d7\" data-start=\"11347\" data-end=\"11365\">Rapid prototypes<\/li>\n<\/ul>\n<hr data-start=\"11367\" data-end=\"11370\" \/>\n<h1 data-section-id=\"1a8df2\" data-start=\"11372\" data-end=\"11388\">Best Practices<\/h1>\n<h2 data-section-id=\"1qn4vk3\" data-start=\"11390\" data-end=\"11414\">Keep Events Immutable<\/h2>\n<p data-start=\"11416\" data-end=\"11447\">Never modify historical events.<\/p>\n<h2 data-section-id=\"1celyva\" data-start=\"11449\" data-end=\"11478\">Use Meaningful Event Names<\/h2>\n<p data-start=\"11480\" data-end=\"11532\">Prefer business language over technical terminology.<\/p>\n<p data-start=\"11534\" data-end=\"11547\">Good example:<\/p>\n<div class=\"relative w-full mt-4 mb-1\">\n<div class=\"\">\n<div class=\"relative\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"border border-token-border-light border-radius-3xl corner-superellipse\/1.1 rounded-3xl\">\n<div class=\"h-full w-full border-radius-3xl bg-token-bg-elevated-secondary corner-superellipse\/1.1 overflow-clip rounded-3xl lxnfua_clipPathFallback\">\n<div class=\"pointer-events-none absolute end-1.5 top-1 z-2 md:end-2 md:top-1\"><\/div>\n<div class=\"relative\">\n<div class=\"pe-11 pt-3\">\n<div class=\"relative z-0 flex max-w-full\">\n<div id=\"code-block-viewer\" dir=\"ltr\" class=\"q9tKkq_viewer cm-editor z-10 light:cm-light dark:cm-light flex h-full w-full flex-col items-stretch \u037cd \u037cr\">\n<div class=\"cm-scroller\">\n<pre class=\"cm-content q9tKkq_readonly m-0\"><code><span>OrderPlaced<\/span>\n<span>PaymentCompleted<\/span>\n<span>InventoryReserved<\/span><\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"\">\n<div class=\"\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p data-start=\"11609\" data-end=\"11615\">Avoid:<\/p>\n<div class=\"relative w-full mt-4 mb-1\">\n<div class=\"\">\n<div class=\"relative\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"h-full min-h-0 min-w-0\">\n<div class=\"border border-token-border-light border-radius-3xl corner-superellipse\/1.1 rounded-3xl\">\n<div class=\"h-full w-full border-radius-3xl bg-token-bg-elevated-secondary corner-superellipse\/1.1 overflow-clip rounded-3xl lxnfua_clipPathFallback\">\n<div class=\"pointer-events-none absolute end-1.5 top-1 z-2 md:end-2 md:top-1\"><\/div>\n<div class=\"relative\">\n<div class=\"pe-11 pt-3\">\n<div class=\"relative z-0 flex max-w-full\">\n<div id=\"code-block-viewer\" dir=\"ltr\" class=\"q9tKkq_viewer cm-editor z-10 light:cm-light dark:cm-light flex h-full w-full flex-col items-stretch \u037cd \u037cr\">\n<div class=\"cm-scroller\">\n<pre class=\"cm-content q9tKkq_readonly m-0\"><code><span>OrderUpdated<\/span>\n<span>DataChanged<\/span><\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"\">\n<div class=\"\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h2 data-section-id=\"v2x5g3\" data-start=\"11655\" data-end=\"11680\">Maintain Thin Commands<\/h2>\n<p data-start=\"11682\" data-end=\"11718\">Commands should express intent only.<\/p>\n<h2 data-section-id=\"1jr5a0p\" data-start=\"11720\" data-end=\"11751\">Use Dedicated Read Databases<\/h2>\n<p data-start=\"11753\" data-end=\"11788\">Optimize read models independently.<\/p>\n<h2 data-section-id=\"1arubc6\" data-start=\"11790\" data-end=\"11813\">Implement Monitoring<\/h2>\n<p data-start=\"11815\" data-end=\"11855\">Track event failures and processing lag.<\/p>\n<hr data-start=\"11857\" data-end=\"11860\" \/>\n<h1 data-section-id=\"1329ug4\" data-start=\"11862\" data-end=\"11878\">Final Thoughts<\/h1>\n<p data-start=\"11880\" data-end=\"12128\">CQRS and Event Sourcing can significantly improve scalability, maintainability, and <a href=\"https:\/\/harshad-sonawane.com\/blog\/monitoring-java-applications-prometheus-grafana-kubernetes\/\">observability<\/a> in complex distributed applications. However, these patterns should be introduced carefully because they add architectural and operational complexity.<\/p>\n<p data-start=\"12130\" data-end=\"12417\">For enterprise-grade systems with high scalability demands and strict auditing requirements, combining CQRS and Event Sourcing with <span class=\"hover:entity-accent entity-underline inline cursor-pointer align-baseline\"><span class=\"whitespace-normal\">Spring Boot<\/span><\/span> and <span class=\"hover:entity-accent entity-underline inline cursor-pointer align-baseline\"><span class=\"whitespace-normal\">Apache Kafka<\/span><\/span> provides a powerful foundation for building resilient event-driven systems.<\/p>\n<p data-start=\"12419\" data-end=\"12682\">Understanding the trade-offs is critical before adopting these patterns in production environments. Start with a clear business problem, introduce these patterns incrementally, and ensure the engineering team understands event-driven design principles thoroughly.<\/p>\n<h1 data-section-id=\"1glbcc5\" data-start=\"13707\" data-end=\"13723\">Reference URLs<\/h1>\n<ul data-start=\"13725\" data-end=\"13968\">\n<li data-section-id=\"btvcid\" data-start=\"13725\" data-end=\"13764\"><span class=\"\" data-state=\"closed\"><a target=\"_blank\" class=\"decorated-link\" rel=\"noopener\" href=\"https:\/\/spring.io\/projects\/spring-boot?utm_source=chatgpt.com\">Spring Boot Official Documentation<\/a><\/span><\/li>\n<li data-section-id=\"u21111\" data-start=\"13765\" data-end=\"13804\"><span class=\"\" data-state=\"closed\"><a target=\"_blank\" class=\"decorated-link\" rel=\"noopener\" href=\"https:\/\/kafka.apache.org\/documentation\/?utm_source=chatgpt.com\">Apache Kafka Documentation<\/a><\/span><\/li>\n<li data-section-id=\"1j40yc5\" data-start=\"13805\" data-end=\"13844\"><span class=\"\" data-state=\"closed\"><a target=\"_blank\" class=\"decorated-link\" rel=\"noopener\" href=\"https:\/\/spring.io\/projects\/spring-kafka?utm_source=chatgpt.com\">Spring for Apache Kafka<\/a><\/span><\/li>\n<li data-section-id=\"4w1vzp\" data-start=\"13845\" data-end=\"13884\"><span class=\"\" data-state=\"closed\"><a target=\"_blank\" class=\"decorated-link\" rel=\"noopener\" href=\"https:\/\/www.postgresql.org\/docs\/?utm_source=chatgpt.com\">PostgreSQL Documentation<\/a><\/span><\/li>\n<li data-section-id=\"yuzy45\" data-start=\"13885\" data-end=\"13926\"><span class=\"\" data-state=\"closed\"><a target=\"_blank\" class=\"decorated-link\" rel=\"noopener\" href=\"https:\/\/martinfowler.com\/bliki\/CQRS.html?utm_source=chatgpt.com\">Martin Fowler CQRS Guide<\/a><\/span><\/li>\n<li data-section-id=\"1flqygl\" data-start=\"13927\" data-end=\"13968\"><span class=\"\" data-state=\"closed\"><a target=\"_blank\" class=\"decorated-link\" rel=\"noopener\" href=\"https:\/\/learn.microsoft.com\/en-us\/azure\/architecture\/patterns\/event-sourcing?utm_source=chatgpt.com\">Event Sourcing Pattern by Microsoft<\/a><\/span><\/li>\n<\/ul>\n\n\n<p class=\"o-typing-delay-100ms ticss-27f7e3e9 wp-block-paragraph\"><o-anim-typing>&lt;> <strong>&#8220;Happy developing, one line at a time!&#8221;<\/strong> &lt;\/><\/o-anim-typing><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Modern enterprise applications often struggle with scalability, complex business workflows, and maintaining consistency across distributed systems. Traditional CRUD-based architectures become difficult to manage as applications evolve and business rules become more sophisticated. This is where CQRS (Command Query Responsibility Segregation) and Event Sourcing emerge as powerful architectural patterns. In this [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":492,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_themeisle_gutenberg_block_has_review":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[113],"tags":[319,296,367,362,66,361,369,216,366,360,363,2,252,9,171,364,368,12,3,365],"class_list":["post-488","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-java-spring-boot-aws-microservices","tag-backend-engineering","tag-cqrs","tag-cqrs-pattern","tag-ddd","tag-distributed-systems","tag-domain-driven-design","tag-enterprise-java","tag-event-driven-architecture-2","tag-event-replay","tag-event-sourcing","tag-event-store","tag-java","tag-kafka","tag-microservices","tag-postgresql","tag-scalable-systems","tag-snapshotting","tag-software-architecture","tag-spring-boot","tag-spring-kafka"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.7 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Implementing CQRS and Event Sourcing in Spring Boot - &lt;&gt;HARSHAD&#039;s Dev Diary&lt;\/&gt;<\/title>\n<meta name=\"description\" content=\"Learn how to implement CQRS and Event Sourcing in Spring Boot using Kafka and PostgreSQL. Explore architecture, event-driven design, aggregates, projections, event replay, snapshotting, and production best practices for scalable microservices\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/harshad-sonawane.com\/blog\/implementing-cqrs-and-event-sourcing-in-spring-boot\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Implementing CQRS and Event Sourcing in Spring Boot - &lt;&gt;HARSHAD&#039;s Dev Diary&lt;\/&gt;\" \/>\n<meta property=\"og:description\" content=\"Learn how to implement CQRS and Event Sourcing in Spring Boot using Kafka and PostgreSQL. Explore architecture, event-driven design, aggregates, projections, event replay, snapshotting, and production best practices for scalable microservices\" \/>\n<meta property=\"og:url\" content=\"https:\/\/harshad-sonawane.com\/blog\/implementing-cqrs-and-event-sourcing-in-spring-boot\/\" \/>\n<meta property=\"og:site_name\" content=\"&lt;&gt;HARSHAD&#039;s Dev Diary&lt;\/&gt;\" \/>\n<meta property=\"article:published_time\" content=\"2026-05-30T05:55:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/harshad-sonawane.com\/blog\/wp-content\/uploads\/2026\/05\/ChatGPT-Image-May-16-2026-07_46_52-PM.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1536\" \/>\n\t<meta property=\"og:image:height\" content=\"1024\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"HS\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"HS\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":[\"Article\",\"BlogPosting\"],\"@id\":\"https:\\\/\\\/harshad-sonawane.com\\\/blog\\\/implementing-cqrs-and-event-sourcing-in-spring-boot\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/harshad-sonawane.com\\\/blog\\\/implementing-cqrs-and-event-sourcing-in-spring-boot\\\/\"},\"author\":{\"name\":\"HS\",\"@id\":\"https:\\\/\\\/harshad-sonawane.com\\\/blog\\\/#\\\/schema\\\/person\\\/d82781218ba30c34fa81b49e8393681e\"},\"headline\":\"Implementing CQRS and Event Sourcing in Spring Boot\",\"datePublished\":\"2026-05-30T05:55:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/harshad-sonawane.com\\\/blog\\\/implementing-cqrs-and-event-sourcing-in-spring-boot\\\/\"},\"wordCount\":943,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/harshad-sonawane.com\\\/blog\\\/#\\\/schema\\\/person\\\/d82781218ba30c34fa81b49e8393681e\"},\"image\":{\"@id\":\"https:\\\/\\\/harshad-sonawane.com\\\/blog\\\/implementing-cqrs-and-event-sourcing-in-spring-boot\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/harshad-sonawane.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/ChatGPT-Image-May-16-2026-07_46_52-PM.png\",\"keywords\":[\"Backend Engineering\",\"CQRS\",\"CQRS Pattern\",\"DDD\",\"Distributed Systems\",\"Domain Driven Design\",\"Enterprise Java\",\"event driven architecture\",\"Event Replay\",\"Event Sourcing\",\"Event Store\",\"Java\",\"Kafka\",\"Microservices\",\"PostgreSQL\",\"Scalable Systems\",\"Snapshotting\",\"Software Architecture\",\"Spring Boot\",\"Spring Kafka\"],\"articleSection\":[\"Java, Spring Boot, AWS, Microservices\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/harshad-sonawane.com\\\/blog\\\/implementing-cqrs-and-event-sourcing-in-spring-boot\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/harshad-sonawane.com\\\/blog\\\/implementing-cqrs-and-event-sourcing-in-spring-boot\\\/\",\"url\":\"https:\\\/\\\/harshad-sonawane.com\\\/blog\\\/implementing-cqrs-and-event-sourcing-in-spring-boot\\\/\",\"name\":\"Implementing CQRS and Event Sourcing in Spring Boot - &lt;&gt;HARSHAD&#039;s Dev Diary&lt;\\\/&gt;\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/harshad-sonawane.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/harshad-sonawane.com\\\/blog\\\/implementing-cqrs-and-event-sourcing-in-spring-boot\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/harshad-sonawane.com\\\/blog\\\/implementing-cqrs-and-event-sourcing-in-spring-boot\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/harshad-sonawane.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/ChatGPT-Image-May-16-2026-07_46_52-PM.png\",\"datePublished\":\"2026-05-30T05:55:00+00:00\",\"description\":\"Learn how to implement CQRS and Event Sourcing in Spring Boot using Kafka and PostgreSQL. Explore architecture, event-driven design, aggregates, projections, event replay, snapshotting, and production best practices for scalable microservices\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/harshad-sonawane.com\\\/blog\\\/implementing-cqrs-and-event-sourcing-in-spring-boot\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/harshad-sonawane.com\\\/blog\\\/implementing-cqrs-and-event-sourcing-in-spring-boot\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/harshad-sonawane.com\\\/blog\\\/implementing-cqrs-and-event-sourcing-in-spring-boot\\\/#primaryimage\",\"url\":\"https:\\\/\\\/harshad-sonawane.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/ChatGPT-Image-May-16-2026-07_46_52-PM.png\",\"contentUrl\":\"https:\\\/\\\/harshad-sonawane.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/ChatGPT-Image-May-16-2026-07_46_52-PM.png\",\"width\":1536,\"height\":1024},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/harshad-sonawane.com\\\/blog\\\/implementing-cqrs-and-event-sourcing-in-spring-boot\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/harshad-sonawane.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Implementing CQRS and Event Sourcing in Spring Boot\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/harshad-sonawane.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/harshad-sonawane.com\\\/blog\\\/\",\"name\":\"Harshad's Dev Diary\",\"description\":\"HARSHAD&#039;s Dev Diary\",\"publisher\":{\"@id\":\"https:\\\/\\\/harshad-sonawane.com\\\/blog\\\/#\\\/schema\\\/person\\\/d82781218ba30c34fa81b49e8393681e\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/harshad-sonawane.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/harshad-sonawane.com\\\/blog\\\/#\\\/schema\\\/person\\\/d82781218ba30c34fa81b49e8393681e\",\"name\":\"HS\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/harshad-sonawane.com\\\/blog\\\/wp-content\\\/uploads\\\/2025\\\/02\\\/about.jpg\",\"url\":\"https:\\\/\\\/harshad-sonawane.com\\\/blog\\\/wp-content\\\/uploads\\\/2025\\\/02\\\/about.jpg\",\"contentUrl\":\"https:\\\/\\\/harshad-sonawane.com\\\/blog\\\/wp-content\\\/uploads\\\/2025\\\/02\\\/about.jpg\",\"width\":400,\"height\":400,\"caption\":\"HS\"},\"logo\":{\"@id\":\"https:\\\/\\\/harshad-sonawane.com\\\/blog\\\/wp-content\\\/uploads\\\/2025\\\/02\\\/about.jpg\"},\"sameAs\":[\"https:\\\/\\\/harshad-sonawane.com\\\/blog\"],\"url\":\"https:\\\/\\\/harshad-sonawane.com\\\/blog\\\/author\\\/admin\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Implementing CQRS and Event Sourcing in Spring Boot - &lt;&gt;HARSHAD&#039;s Dev Diary&lt;\/&gt;","description":"Learn how to implement CQRS and Event Sourcing in Spring Boot using Kafka and PostgreSQL. Explore architecture, event-driven design, aggregates, projections, event replay, snapshotting, and production best practices for scalable microservices","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/harshad-sonawane.com\/blog\/implementing-cqrs-and-event-sourcing-in-spring-boot\/","og_locale":"en_US","og_type":"article","og_title":"Implementing CQRS and Event Sourcing in Spring Boot - &lt;&gt;HARSHAD&#039;s Dev Diary&lt;\/&gt;","og_description":"Learn how to implement CQRS and Event Sourcing in Spring Boot using Kafka and PostgreSQL. Explore architecture, event-driven design, aggregates, projections, event replay, snapshotting, and production best practices for scalable microservices","og_url":"https:\/\/harshad-sonawane.com\/blog\/implementing-cqrs-and-event-sourcing-in-spring-boot\/","og_site_name":"&lt;&gt;HARSHAD&#039;s Dev Diary&lt;\/&gt;","article_published_time":"2026-05-30T05:55:00+00:00","og_image":[{"width":1536,"height":1024,"url":"https:\/\/harshad-sonawane.com\/blog\/wp-content\/uploads\/2026\/05\/ChatGPT-Image-May-16-2026-07_46_52-PM.png","type":"image\/png"}],"author":"HS","twitter_card":"summary_large_image","twitter_misc":{"Written by":"HS","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":["Article","BlogPosting"],"@id":"https:\/\/harshad-sonawane.com\/blog\/implementing-cqrs-and-event-sourcing-in-spring-boot\/#article","isPartOf":{"@id":"https:\/\/harshad-sonawane.com\/blog\/implementing-cqrs-and-event-sourcing-in-spring-boot\/"},"author":{"name":"HS","@id":"https:\/\/harshad-sonawane.com\/blog\/#\/schema\/person\/d82781218ba30c34fa81b49e8393681e"},"headline":"Implementing CQRS and Event Sourcing in Spring Boot","datePublished":"2026-05-30T05:55:00+00:00","mainEntityOfPage":{"@id":"https:\/\/harshad-sonawane.com\/blog\/implementing-cqrs-and-event-sourcing-in-spring-boot\/"},"wordCount":943,"commentCount":0,"publisher":{"@id":"https:\/\/harshad-sonawane.com\/blog\/#\/schema\/person\/d82781218ba30c34fa81b49e8393681e"},"image":{"@id":"https:\/\/harshad-sonawane.com\/blog\/implementing-cqrs-and-event-sourcing-in-spring-boot\/#primaryimage"},"thumbnailUrl":"https:\/\/harshad-sonawane.com\/blog\/wp-content\/uploads\/2026\/05\/ChatGPT-Image-May-16-2026-07_46_52-PM.png","keywords":["Backend Engineering","CQRS","CQRS Pattern","DDD","Distributed Systems","Domain Driven Design","Enterprise Java","event driven architecture","Event Replay","Event Sourcing","Event Store","Java","Kafka","Microservices","PostgreSQL","Scalable Systems","Snapshotting","Software Architecture","Spring Boot","Spring Kafka"],"articleSection":["Java, Spring Boot, AWS, Microservices"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/harshad-sonawane.com\/blog\/implementing-cqrs-and-event-sourcing-in-spring-boot\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/harshad-sonawane.com\/blog\/implementing-cqrs-and-event-sourcing-in-spring-boot\/","url":"https:\/\/harshad-sonawane.com\/blog\/implementing-cqrs-and-event-sourcing-in-spring-boot\/","name":"Implementing CQRS and Event Sourcing in Spring Boot - &lt;&gt;HARSHAD&#039;s Dev Diary&lt;\/&gt;","isPartOf":{"@id":"https:\/\/harshad-sonawane.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/harshad-sonawane.com\/blog\/implementing-cqrs-and-event-sourcing-in-spring-boot\/#primaryimage"},"image":{"@id":"https:\/\/harshad-sonawane.com\/blog\/implementing-cqrs-and-event-sourcing-in-spring-boot\/#primaryimage"},"thumbnailUrl":"https:\/\/harshad-sonawane.com\/blog\/wp-content\/uploads\/2026\/05\/ChatGPT-Image-May-16-2026-07_46_52-PM.png","datePublished":"2026-05-30T05:55:00+00:00","description":"Learn how to implement CQRS and Event Sourcing in Spring Boot using Kafka and PostgreSQL. Explore architecture, event-driven design, aggregates, projections, event replay, snapshotting, and production best practices for scalable microservices","breadcrumb":{"@id":"https:\/\/harshad-sonawane.com\/blog\/implementing-cqrs-and-event-sourcing-in-spring-boot\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/harshad-sonawane.com\/blog\/implementing-cqrs-and-event-sourcing-in-spring-boot\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/harshad-sonawane.com\/blog\/implementing-cqrs-and-event-sourcing-in-spring-boot\/#primaryimage","url":"https:\/\/harshad-sonawane.com\/blog\/wp-content\/uploads\/2026\/05\/ChatGPT-Image-May-16-2026-07_46_52-PM.png","contentUrl":"https:\/\/harshad-sonawane.com\/blog\/wp-content\/uploads\/2026\/05\/ChatGPT-Image-May-16-2026-07_46_52-PM.png","width":1536,"height":1024},{"@type":"BreadcrumbList","@id":"https:\/\/harshad-sonawane.com\/blog\/implementing-cqrs-and-event-sourcing-in-spring-boot\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/harshad-sonawane.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Implementing CQRS and Event Sourcing in Spring Boot"}]},{"@type":"WebSite","@id":"https:\/\/harshad-sonawane.com\/blog\/#website","url":"https:\/\/harshad-sonawane.com\/blog\/","name":"Harshad's Dev Diary","description":"HARSHAD&#039;s Dev Diary","publisher":{"@id":"https:\/\/harshad-sonawane.com\/blog\/#\/schema\/person\/d82781218ba30c34fa81b49e8393681e"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/harshad-sonawane.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/harshad-sonawane.com\/blog\/#\/schema\/person\/d82781218ba30c34fa81b49e8393681e","name":"HS","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/harshad-sonawane.com\/blog\/wp-content\/uploads\/2025\/02\/about.jpg","url":"https:\/\/harshad-sonawane.com\/blog\/wp-content\/uploads\/2025\/02\/about.jpg","contentUrl":"https:\/\/harshad-sonawane.com\/blog\/wp-content\/uploads\/2025\/02\/about.jpg","width":400,"height":400,"caption":"HS"},"logo":{"@id":"https:\/\/harshad-sonawane.com\/blog\/wp-content\/uploads\/2025\/02\/about.jpg"},"sameAs":["https:\/\/harshad-sonawane.com\/blog"],"url":"https:\/\/harshad-sonawane.com\/blog\/author\/admin\/"}]}},"jetpack_publicize_connections":[],"_links":{"self":[{"href":"https:\/\/harshad-sonawane.com\/blog\/wp-json\/wp\/v2\/posts\/488","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/harshad-sonawane.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/harshad-sonawane.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/harshad-sonawane.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/harshad-sonawane.com\/blog\/wp-json\/wp\/v2\/comments?post=488"}],"version-history":[{"count":3,"href":"https:\/\/harshad-sonawane.com\/blog\/wp-json\/wp\/v2\/posts\/488\/revisions"}],"predecessor-version":[{"id":493,"href":"https:\/\/harshad-sonawane.com\/blog\/wp-json\/wp\/v2\/posts\/488\/revisions\/493"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/harshad-sonawane.com\/blog\/wp-json\/wp\/v2\/media\/492"}],"wp:attachment":[{"href":"https:\/\/harshad-sonawane.com\/blog\/wp-json\/wp\/v2\/media?parent=488"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/harshad-sonawane.com\/blog\/wp-json\/wp\/v2\/categories?post=488"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/harshad-sonawane.com\/blog\/wp-json\/wp\/v2\/tags?post=488"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}