{"id":1724,"date":"2010-01-27T12:27:50","date_gmt":"2010-01-27T11:27:50","guid":{"rendered":"http:\/\/blog.jteam.nl\/2010\/01\/27\/cqrs-designing-domain-events\/"},"modified":"2010-01-27T12:27:50","modified_gmt":"2010-01-27T11:27:50","slug":"cqrs-designing-domain-events","status":"publish","type":"post","link":"https:\/\/trifork.nl\/blog\/cqrs-designing-domain-events\/","title":{"rendered":"CQRS &#8211; Designing domain events"},"content":{"rendered":"<p><a title=\"AxonFramework logo\" href=\"http:\/\/www.axonframework.org\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" style=\"margin: 5px 10px 10px 0px;border: 0px\" title=\"logo\" alt=\"logo\" src=\"http:\/\/blog.jteam.nl\/wp-content\/uploads\/2010\/01\/logo.png\" width=\"100\" height=\"100\" align=\"left\" border=\"0\"><\/a> Command-Query Responsibility Segregation (CQRS) is slowly but steadily gaining ground as an architecture that helps developers to develop scalable, extensible and maintainable applications. Events play a major role in this architecture, and the way you design these events greatly influence the extensibility of your application.<\/p>\n<p>In this post, I describe some CQRS event basics and design considerations that help keep your application extensible.<\/p>\n<p><!--more--><\/p>\n<h2>The role of the domain event<\/h2>\n<p>In CQRS, domain events are the source of all application state changes. The diagram below shows a high-level overview of a CQRS architecture. The separation of the components that deal with commands and those that deal with queries is clearly visible.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" style=\"float: none;margin-left: auto;margin-right: auto;border: 0px\" title=\"cqrs_architecture-highlevel\" alt=\"cqrs_architecture-highlevel\" src=\"http:\/\/blog.jteam.nl\/wp-content\/uploads\/2010\/01\/cqrs_architecturehighlevel.png\" width=\"420\" height=\"327\" border=\"0\"><\/p>\n<p>When a command is executed, it will (most likely) change state of one or more aggregates (see DDD definition of aggregate <a href=\"http:\/\/domaindrivendesign.org\/node\/88\" target=\"_blank\" rel=\"noopener\">here<\/a>). As a result of these state changes, one or more events are dispatched.<\/p>\n<p>These events are picked up by Event Handling Components that do whatever they were built to do. Common Event Handling components are those that update database tables in the query database, or those that send an email notification to a user. You can also use Event Handlers to execute commands on related aggregates.<\/p>\n<p>The command handling component is not aware of the listeners that will act on the generated events. This is an important feature to make an application extensible. The downside is that you cannot foresee how events will be used and what information these event handlers will need.<\/p>\n<h2>Information contained in an event<\/h2>\n<p>Since events are broadcasted throughout the entire application, events should contain the information needed by the variety of possible event listeners that exist or might exist in the future. It is impossible to exactly predict what information is needed by event handling components. However, there are a few guidelines that will cover most of the cases.<\/p>\n<p>Recently, someone asked me for advice on event design. He asked me if it was a good idea to use an \u201cCustomerDetailsModifiedEvent\u201d, which would contain the full customer details of the customer, after the change was applied. Although this sounds safe to do, it will get you in serious trouble at a later stage. I\u2019ll go into that a little later.<\/p>\n<p>Domain events should be as specific as possible. If only the address changed on a Customer, consider using an AddressChangedEvent. That event would then contain the new address. This allows components acting on these events to listen to more specific types of events. If you want to send a (paper) letter to someone if his address changed, the \u201cCustomerDetailsModifiedEvent\u201d won\u2019t get you very far, as you don\u2019t have a way to find out what exactly changed.<\/p>\n<p>In some cases, it might be important to know the state as it was before the command was executed. For example, if it is vital for your application to know whether the person moved to another country (because the letter template is different in these cases, for example), then you should also provide the old address in the event. Since the event is generated by the component that also makes the actual change, this shouldn\u2019t be too hard to implement.<\/p>\n<p><pre class=\"brush: java; title: ; notranslate\" title=\"\">&amp;lt;br&amp;gt;\npublic class AddressChangedEvent extends DomainEvent {&amp;lt;\/p&amp;gt;\n&amp;lt;p&amp;gt;    private final Address newAddress;&amp;lt;br&amp;gt;\n    private final Address oldAddress;&amp;lt;\/p&amp;gt;\n&amp;lt;p&amp;gt;    public AddressChangedEvent(Address oldAddress, Address newAddress) {&amp;lt;br&amp;gt;\n        this.oldAddress = oldAddress;&amp;lt;br&amp;gt;\n        this.newAddress = newAddress;&amp;lt;br&amp;gt;\n    }&amp;lt;\/p&amp;gt;\n&amp;lt;p&amp;gt;    public Address getNewAddress() {&amp;lt;br&amp;gt;\n        return newAddress;&amp;lt;br&amp;gt;\n    }&amp;lt;\/p&amp;gt;\n&amp;lt;p&amp;gt;    public Address getOldAddress() {&amp;lt;br&amp;gt;\n        return oldAddress;&amp;lt;br&amp;gt;\n    }&amp;lt;br&amp;gt;\n}&amp;lt;br&amp;gt;\n<\/pre><\/p>\n<p>The code sample above shows the basic information contained in an AddressChangedEvent in case it is important to know the address of a customer before and after the modification. In this sample, the DomainEvent will contain information about the customer on which the address change was applied. Typically, this information is limited to the unique identifier of the aggregate.<\/p>\n<h2>Include the intent of the change<\/h2>\n<p>Let\u2019s assume that our business case requires us to send a letter to each customer that changes address. This letter serves as some sort of validation that the address exists and gives the customer feedback that the address change was successfully handled.<\/p>\n<p>In CQRS, we would just create a Event Handling Component that listens to events of type AddressChangedEvent and automatically send a letter to this customer. The information needed for the letter, such as customer name and gender are queried in the query database, since they are not contained in the event itself.<\/p>\n<p>Consider an event with the following information:<\/p>\n<p>AddressChangedEvent {<\/p>\n<p>&#8211; aggregateId 123<\/p>\n<p>&#8211; newAddress (\u201csomeStreat 2\u201d, &#8220;13432\u201d, \u201cSomeCIty\u201d) &lt;- notice the typo in the street name<\/p>\n<p>&#8211; oldAdress (\u2026)<\/p>\n<p>As a result of this event, a letter is sent. It is very unlikely that the typo in the street name will cause the letter not to arrive at the destination.<\/p>\n<p>A little later, a sales representative notices the typo in the street name and want to change the address. This change will cause another letter to be sent, most likely to the same address. That\u2019s not really the signal the business likes to send out.<\/p>\n<p>In this scenario, we have captured two different intents of address changes: one is to report that a customer moved to another address, the other is to make a correction in an existing address. The way we deal with these different scenario\u2019s is different.<\/p>\n<p>Some components, like a database updaters, typically don\u2019t care about intent. They will change the address to the new one, regardless of the reason. Furthermore, the information needed by listeners in both scenario\u2019s is identical.<\/p>\n<p>When designing events, consider making an abstract event type that defines \u201cwhat\u201d has changed. For example, an abstract AddressChangedEvent. We make it abstract, because we never want an instance of this type. This abstract then has a subclass for each intent of the change, representing the \u201cwhy\u201d of the state change. For example, AddressCorrectionEvent and CustomerMovedEvent. Since they both extend the abstract AddressChangedEvent, the both contain information about the old and new address.<\/p>\n<p>Our event handling components now have a choice. If they don\u2019t care about intent, such as the database updater, they will handle the abstract AddressChangedEvent. If they do, like our letter sender, they can listen to intent specific subclasses. In this case, the letter sender would only act on events of type CustomerMovedEvent.<\/p>\n<h2>Event immutability<\/h2>\n<p>Domain events represent a notification of a state change of an aggregate. It is a representation of something that happened. Whatever you do, what happened has happened. That said, it doesn\u2019t make much sense to change any information in the event while it is being processed.<\/p>\n<p>In CQRS, events are ubiquitous. This means that any component anywhere in the application could listen to any event. Once properties on these events start to change, it is very hard (if not impossible) to predict which component saw which information on the event.<\/p>\n<p>Therefore, make sure all information contained in the event is immutable. At least from the time the event is dispatched. In java, and likely also in other programming languages, making fields immutable provide valuable multi-threading guarantees.<\/p>\n<h2>Event design in the Axon Framework<\/h2>\n<p>Recently, we released version 0.3 of the Axon Framework, an open source framework that helps you with the implementation of applications with a CQRS architecture. Axon Framework provides base implementations for most of the components that make up a CQRS architecture, such as some base classes for events.<\/p>\n<p>All domain events should extend the abstract DomainEvent class. Axon will then ensure that the correct aggregate identifier is registered on the event and will also set a sequence number on the event that allows you to see in which order events were generated for an aggregate. However, the rules and guidelines mentioned above still apply to all domain events.<\/p>\n<p>Starting at version 0.4 (planned for release mid February 2010), Axon Framework also provides support for Application Events and System Events. The former are events that do not represent a state change in an aggregate, but might be of importance to event handling components. The latter provide information about state changes of application components. They could, for example, report that a database is down or a mail server cannot be reached.<\/p>\n<p>For more information about the Axon Framework, visit the project website: <a href=\"http:\/\/www.axonframework.org\" target=\"_blank\" rel=\"noopener\">www.axonframework.org<\/a>.<\/p>\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/bit.ly\/3BAo305\" target=\"_blank\" rel=\"noreferrer noopener\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"256\" src=\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png\" alt=\"\" class=\"wp-image-20303\" srcset=\"https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png 1024w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-300x75.png 300w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-768x192.png 768w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1536x384.png 1536w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-2048x512.png 2048w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1920x480.png 1920w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>Command-Query Responsibility Segregation (CQRS) is slowly but steadily gaining ground as an architecture that helps developers to develop scalable, extensible and maintainable applications. Events play a major role in this architecture, and the way you design these events greatly influence the extensibility of your application. In this post, I describe some CQRS event basics and [&hellip;]<\/p>\n","protected":false},"author":14,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"content-type":"","footnotes":""},"categories":[81,10],"tags":[140,80,46,170],"class_list":["post-1724","post","type-post","status-publish","format-standard","hentry","category-axon-framework","category-development","tag-architecture","tag-axon-framework","tag-cqrs","tag-ddd"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.4 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>CQRS &#8211; Designing domain events - Trifork Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/trifork.nl\/blog\/cqrs-designing-domain-events\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"CQRS &#8211; Designing domain events - Trifork Blog\" \/>\n<meta property=\"og:description\" content=\"Command-Query Responsibility Segregation (CQRS) is slowly but steadily gaining ground as an architecture that helps developers to develop scalable, extensible and maintainable applications. Events play a major role in this architecture, and the way you design these events greatly influence the extensibility of your application. In this post, I describe some CQRS event basics and [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/trifork.nl\/blog\/cqrs-designing-domain-events\/\" \/>\n<meta property=\"og:site_name\" content=\"Trifork Blog\" \/>\n<meta property=\"article:published_time\" content=\"2010-01-27T11:27:50+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/blog.jteam.nl\/wp-content\/uploads\/2010\/01\/logo.png\" \/>\n<meta name=\"author\" content=\"Allard Buijze\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Allard Buijze\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/trifork.nl\/blog\/cqrs-designing-domain-events\/\",\"url\":\"https:\/\/trifork.nl\/blog\/cqrs-designing-domain-events\/\",\"name\":\"CQRS &#8211; Designing domain events - Trifork Blog\",\"isPartOf\":{\"@id\":\"https:\/\/trifork.nl\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/trifork.nl\/blog\/cqrs-designing-domain-events\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/trifork.nl\/blog\/cqrs-designing-domain-events\/#primaryimage\"},\"thumbnailUrl\":\"http:\/\/blog.jteam.nl\/wp-content\/uploads\/2010\/01\/logo.png\",\"datePublished\":\"2010-01-27T11:27:50+00:00\",\"author\":{\"@id\":\"https:\/\/trifork.nl\/blog\/#\/schema\/person\/a4e232a11dc57a2c4c581956ce6fde63\"},\"breadcrumb\":{\"@id\":\"https:\/\/trifork.nl\/blog\/cqrs-designing-domain-events\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/trifork.nl\/blog\/cqrs-designing-domain-events\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/trifork.nl\/blog\/cqrs-designing-domain-events\/#primaryimage\",\"url\":\"http:\/\/blog.jteam.nl\/wp-content\/uploads\/2010\/01\/logo.png\",\"contentUrl\":\"http:\/\/blog.jteam.nl\/wp-content\/uploads\/2010\/01\/logo.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/trifork.nl\/blog\/cqrs-designing-domain-events\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/trifork.nl\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"CQRS &#8211; Designing domain events\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/trifork.nl\/blog\/#website\",\"url\":\"https:\/\/trifork.nl\/blog\/\",\"name\":\"Trifork Blog\",\"description\":\"Keep updated on the technical solutions Trifork is working on!\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/trifork.nl\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/trifork.nl\/blog\/#\/schema\/person\/a4e232a11dc57a2c4c581956ce6fde63\",\"name\":\"Allard Buijze\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/trifork.nl\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/3e7130b2465615e105b1addd400a3f06?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/3e7130b2465615e105b1addd400a3f06?s=96&d=mm&r=g\",\"caption\":\"Allard Buijze\"},\"description\":\"Allard (@allardbz) is CTO of Trifork Amsterdam and founder of Axon Framework. He is a trainer and speaker at conferences on topics related to scalable architecture and domain driven design. He strongly believes that good craftsmanship can only be achieved through continuous and intensive exchange of experience with others. The last years, he has been investigating and applying CQRS to a number of projects. As a result, he created the Axon Framework, an open source Java framework that helps developers create scalable and extensible applications. Axon has a growing community and has already been successfully introduced in several high-profile projects around the world.\",\"url\":\"https:\/\/trifork.nl\/blog\/author\/allard\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"CQRS &#8211; Designing domain events - Trifork Blog","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:\/\/trifork.nl\/blog\/cqrs-designing-domain-events\/","og_locale":"en_US","og_type":"article","og_title":"CQRS &#8211; Designing domain events - Trifork Blog","og_description":"Command-Query Responsibility Segregation (CQRS) is slowly but steadily gaining ground as an architecture that helps developers to develop scalable, extensible and maintainable applications. Events play a major role in this architecture, and the way you design these events greatly influence the extensibility of your application. In this post, I describe some CQRS event basics and [&hellip;]","og_url":"https:\/\/trifork.nl\/blog\/cqrs-designing-domain-events\/","og_site_name":"Trifork Blog","article_published_time":"2010-01-27T11:27:50+00:00","og_image":[{"url":"http:\/\/blog.jteam.nl\/wp-content\/uploads\/2010\/01\/logo.png","type":"","width":"","height":""}],"author":"Allard Buijze","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Allard Buijze","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/trifork.nl\/blog\/cqrs-designing-domain-events\/","url":"https:\/\/trifork.nl\/blog\/cqrs-designing-domain-events\/","name":"CQRS &#8211; Designing domain events - Trifork Blog","isPartOf":{"@id":"https:\/\/trifork.nl\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/trifork.nl\/blog\/cqrs-designing-domain-events\/#primaryimage"},"image":{"@id":"https:\/\/trifork.nl\/blog\/cqrs-designing-domain-events\/#primaryimage"},"thumbnailUrl":"http:\/\/blog.jteam.nl\/wp-content\/uploads\/2010\/01\/logo.png","datePublished":"2010-01-27T11:27:50+00:00","author":{"@id":"https:\/\/trifork.nl\/blog\/#\/schema\/person\/a4e232a11dc57a2c4c581956ce6fde63"},"breadcrumb":{"@id":"https:\/\/trifork.nl\/blog\/cqrs-designing-domain-events\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/trifork.nl\/blog\/cqrs-designing-domain-events\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/trifork.nl\/blog\/cqrs-designing-domain-events\/#primaryimage","url":"http:\/\/blog.jteam.nl\/wp-content\/uploads\/2010\/01\/logo.png","contentUrl":"http:\/\/blog.jteam.nl\/wp-content\/uploads\/2010\/01\/logo.png"},{"@type":"BreadcrumbList","@id":"https:\/\/trifork.nl\/blog\/cqrs-designing-domain-events\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/trifork.nl\/blog\/"},{"@type":"ListItem","position":2,"name":"CQRS &#8211; Designing domain events"}]},{"@type":"WebSite","@id":"https:\/\/trifork.nl\/blog\/#website","url":"https:\/\/trifork.nl\/blog\/","name":"Trifork Blog","description":"Keep updated on the technical solutions Trifork is working on!","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/trifork.nl\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/trifork.nl\/blog\/#\/schema\/person\/a4e232a11dc57a2c4c581956ce6fde63","name":"Allard Buijze","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/trifork.nl\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/3e7130b2465615e105b1addd400a3f06?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/3e7130b2465615e105b1addd400a3f06?s=96&d=mm&r=g","caption":"Allard Buijze"},"description":"Allard (@allardbz) is CTO of Trifork Amsterdam and founder of Axon Framework. He is a trainer and speaker at conferences on topics related to scalable architecture and domain driven design. He strongly believes that good craftsmanship can only be achieved through continuous and intensive exchange of experience with others. The last years, he has been investigating and applying CQRS to a number of projects. As a result, he created the Axon Framework, an open source Java framework that helps developers create scalable and extensible applications. Axon has a growing community and has already been successfully introduced in several high-profile projects around the world.","url":"https:\/\/trifork.nl\/blog\/author\/allard\/"}]}},"_links":{"self":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/posts\/1724","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/users\/14"}],"replies":[{"embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/comments?post=1724"}],"version-history":[{"count":0,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/posts\/1724\/revisions"}],"wp:attachment":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/media?parent=1724"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/categories?post=1724"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/tags?post=1724"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}