CQRS Journey Guide

CQRS_Journey_Guide

User Manual: Pdf

Open the PDF directly: View PDF PDF.
Page Count: 376 [warning: Documents this large are best viewed by clicking the View PDF Link!]

Exploring CQRS and
Event Sourcing
A journey into high scalability, availability,
and maintainability with Windows Azure
Exploring CQRS and
Event Sourcing
A journey into high scalability, availability,
and maintainability with Windows Azure
Dominic Betts
Julián Domínguez
Grigori Melnik
Fernando Simonazzi
Mani Subramanian
978-1-62114-016-0
This document is provided “as-is”. Information and views expressed in
this document, including URL and other Internet Web site references,
may change without notice.
Some examples depicted herein are provided for illustration only and are
fictitious. No real association or connection is intended or should be
inferred.
This document does not provide you with any legal rights to any
intellectual property in any Microsoft product. You may copy and use
this document for your internal, reference purposes. You may modify this
document for your internal, reference purposes
© 2012 Microsoft. All rights reserved.
Microsoft, MSDN, SQL Azure, SQL Server, Visual Studio, Windows, and
Windows Azure are trademarks of the Microsoft group of companies. All
other trademarks are property of their respective owners.
What other readers are saying about this guide xvii
Foreword by Greg Young xxi
Preface xxiii
Why we created this guidance now xxiii
How is this guidance structured? xxiii
A CQRS journey xxiv
CQRS reference xxv
Tales from the trenches xxv
A CQRS journey xxv
CQRS reference xxvi
Tales from the trenches xxvi
Selecting the domain for the RI xxvi
Arrow legend xxvii
Where to go for more information xxviii
The Crew xxix
Journey 1: Our Domain: Conference Management System 1
The Contoso Corporation 1
Who is coming with us on the journey? 2
The Contoso Conference Management System 3
Overview of the system 3
Selling seats for a conference 4
Creating a conference 4
Nonfunctional requirements 4
Scalability 4
Flexibility 5
Beginning the journey 5
More information 5
Contents
vi
Journey 2: Decomposing the Domain 7
Definitions used in this chapter 7
Bounded contexts in the conference management system 8
Bounded contexts not included 9
The context map for the Contoso Conference Management
System 10
Why did we choose these bounded contexts? 11
More information 11
Journey 3: Orders and Registrations Bounded Context 13
A description of the bounded context 13
Working definitions for this chapter 14
Domain definitions (ubiquitous language) 15
Requirements for creating orders 17
Architecture 18
Patterns and concepts 18
Validation 23
Transaction boundaries 24
Concurrency 25
Aggregates and aggregate roots 25
Implementation details 25
High-level architecture 26
1. Querying the read model 27
2. Issuing commands 28
3. Handling commands 28
4. Initiating business logic in the domain 29
5. Persisting the changes 29
6. Polling the read model 29
Inside the write model 31
Aggregates 31
Aggregates and process managers 34
Infrastructure 40
Using the Windows Azure Service Bus 42
Delivering a command to a single recipient 44
Why have separate CommandBus and EventBus
classes? 48
How scalable is this approach? 48
How robust is this approach? 48
What is the granularity of a topic and a subscription? 48
How are commands and events serialized? 49
Impact on testing 49
Summary 52
More information 52
vii
Journey 4: Extending and Enhancing the Orders and
Registrations Bounded Context 53
Changes to the bounded context 53
Working definitions for this chapter 53
User stories 54
Implement a login using a record locator 54
Tell the registrant how much time remains to complete
an order 55
Enable a registrant to create an order that includes
multiple seat types 55
Architecture 55
Patterns and concepts 56
Record locators 56
Querying the read side 56
Storing denormalized views in a database 57
Making information about partially fullled orders
available to the read side 60
CQRS command validation 61
The countdown timer and the read model 62
Implementation details 62
The order access code record locator 63
The countdown timer 64
Using ASP.NET MVC validation for commands 66
Pushing changes to the read side 69
Querying the read side 72
Refactoring the SeatsAvailability aggregate 73
The AddSeats method 74
Impact on testing 74
Acceptance tests and the domain expert 74
Defining acceptance tests using SpecFlow features 74
Making the tests executable 76
Using tests to help developers understand message flows 81
A journey into code comprehension: A tale of pain, relief,
and learning 83
Testing is important 83
Domain tests 84
The other side of the coin 86
Summary 90
More information 90
Journey 5: Preparing for the V1 Release 91
The Contoso Conference Management System V1 release 91
Working definitions for this chapter 91
User stories 92
Ubiquitous language definitions 92
Conference Management bounded context user stories 92
Ordering and Registration bounded context user stories 92
viii
Architecture 93
Conference Management bounded context 97
Patterns and concepts 97
Event sourcing 97
Identifying aggregates 98
Task-based UI 99
CRUD 101
Integration between bounded contexts 101
Pushing changes from the Conference Management
bounded context 102
Pushing changes to the Conference Management
bounded context 104
Choosing when to update the read-side data 105
Distributed transactions and event sourcing 105
Autonomy versus authority 105
Favoring autonomy 106
Favoring authority 106
Choosing between autonomy and authority 106
Approaches to implementing the read side 107
Eventual consistency 107
Implementation details 108
The Conference Management bounded context 108
Integration with the Orders and Registration bounded
context 108
The Payments bounded context 109
Integration with online payment services, eventual
consistency, and command validation 111
Event sourcing 113
Raising events when the state of an aggregate changes 113
Persisting events to the event store 117
Replaying events to rebuild state 118
Issues with the simple event store implementation 120
Windows Azure table storage-based event store 120
Calculating totals 122
Impact on testing 123
Timing issues 123
Involving the domain expert 123
Summary 124
More information 124
Journey 6: Versioning Our System 125
Working definitions for this chapter 125
User stories 126
No down time upgrade 126
Display remaining seat quantities 126
Handle zero-cost seats 126
Architecture 126
ix
Patterns and concepts 127
Handling changes to events definitions 128
Mapping/filtering event messages in the infrastructure 128
Handling multiple message versions in the aggregates 128
Honoring message idempotency 128
Avoid processing events multiple times 129
Persisting integration events 131
Message ordering 133
Implementation details 133
Adding support for zero-cost orders 134
Changes to the RegistrationProcessManager class 134
Changes to the UI 134
Data migration 136
Displaying remaining seats in the UI 138
Adding information about remaining seat quantities
to the read model 138
Modifying the UI to display remaining seat quantities 140
Data migration 140
De-duplicating command messages 141
Guaranteeing message ordering 142
Persisting events from the Conference Management
bounded context 146
Adding additional metadata to the messages 146
Capturing and persisting messages to the message log 146
Data migration 148
Migrating from V1 to V2 150
Generating past log messages for the Conference
Management bounded context 151
Migrating the event sourcing events 151
Rebuilding the read models 151
Impact on testing 151
SpecFlow revisited 152
Discovering a bug during the migration 155
Summary 155
More information 155
Journey 7: Adding Resilience and Optimizing Performance 157
Working definitions for this chapter 157
Architecture 158
Adding resilience 159
Making the system resilient when an event is reprocessed 161
Ensuring that commands are always sent 161
Optimizing performance 162
UI flow before optimization 162
Optimizing the UI 163
UI optimization 1 164
UI optimization 2 165
x
Optimizing the infrastructure 165
Sending and receiving commands and events
asynchronously 165
Optimizing command processing 166
Using snapshots with event sourcing 166
Publishing events in parallel 167
Filtering messages in subscriptions 167
Creating a dedicated receiver for the SeatsAvailability
aggregate 167
Caching conference information 167
Partitioning the Service Bus 168
Other optimizations 168
Further changes that would improve performance 169
Further changes that would enhance scalability 171
No down-time migration 172
Rebuilding the read models 173
Implementation details 174
Hardening the RegistrationProcessManager class 174
Detecting out-of-order SeatsReserved events 175
Detecting duplicate OrderPlaced events 178
Creating a pseudo transaction when the
RegistrationProcessManager class saves its state
and sends a command 178
Optimizing the UI flow 181
Receiving, completing, and sending messages
asynchronously 186
Receiving messages asynchronously 186
Completing messages asynchronously 186
Sending messages asynchronously 186
Handling commands synchronously and in-process 186
Implementing snapshots with the memento pattern 189
Publishing events in parallel 191
Filtering messages in subscriptions 192
Creating a dedicated SessionSubscriptionReceiver
instance for the SeatsAvailability aggregate 193
Caching read-model data 194
Using multiple topics to partition the service bus 195
Other optimizing and hardening changes 196
Sequential GUIDs 196
Asynchronous ASP.NET MVC controllers. 198
Using prefetch with Windows Azure Service Bus 198
Accepting multiple sessions in parallel 199
Adding an optimistic concurrency check 199
Adding a time-to-live value to the
MakeSeatReservation command 199
Reducing the number of round-trips to the database 199
xi
Impact on testing 200
Integration tests 200
User interface tests 200
Summary 200
More information 200
Journey 8: Epilogue: Lessons Learned 201
What did we learn? 201
Performance matters 201
Implementing a message-driven system is far from simple 202
The cloud has challenges 203
CQRS is different 204
Event sourcing and transaction logging 205
Involving the domain expert 206
When to use CQRS 206
What would we do differently if we started over? 207
Start with a solid infrastructure for messaging and
persistence 207
Leverage the capabilities of the infrastructure more 207
Adopt a more systematic approach to implementing
process managers 208
Partition the application differently 208
Organize the development team differently 208
Evaluate how appropriate the domain and the bounded
contexts are for the CQRS pattern 208
Plan for performance 208
Think about the UI differently 209
Explore some additional benefits of event sourcing 209
Explore the issues associated with integrating bounded
contexts 210
More information 210
Reference 1: CQRS in Context 211
What is domain-driven design? 212
Domain-driven design: concepts and terminology 212
Domain model 213
Ubiquitous language 213
Entities, value objects, and services 214
Aggregates and aggregate roots 215
Bounded contexts 215
Anti-corruption layers 217
Context maps 218
Bounded contexts and multiple architectures 218
Bounded contexts and multiple development teams 219
Maintaining multiple bounded contexts 220
CQRS and DDD 220
More information 221
xii
Reference 2: Introducing the Command Query
Responsibility Segregation Pattern 223
What is CQRS? 223
Read and write sides 225
CQRS and domain-driven design 227
Introducing commands, events, and messages 228
Why should I use CQRS? 230
Scalability 230
Reduced complexity 231
Flexibility 231
Focus on the business 232
Facilitates building task-based UIs 232
Barriers to adopting the CQRS pattern 232
When should I use CQRS? 232
Collaborative domains 233
Stale data 233
Moving to the cloud 234
When should I avoid CQRS? 234
Summary 234
More information 234
Reference 3: Introducing Event Sourcing 235
What is event sourcing? 236
Comparing using an ORM layer with event sourcing 236
Why should I use event sourcing? 240
Event sourcing concerns 242
CQRS/ES 243
Standalone event sourcing 245
Event stores 245
Basic requirements 245
Underlying storage 245
Performance, scalability, and consistency 245
More information 246
Reference 4: A CQRS and ES Deep Dive 247
Introduction 247
Read models and write models 247
Commands and data transfer objects 247
Domain-driven design (DDD) and aggregates 248
Data and normalization 248
Events and event sourcing 248
Eventual consistency 248
Defining aggregates in the domain model 249
Aggregates and object-relational mapping layers 249
Aggregates and event sourcing 250
xiii
Commands and command handlers 252
Commands 253
Example code 253
Command handlers 254
Commands and optimistic concurrency 256
Events and event handlers 256
Events and intent 256
How to model intent 258
Events 259
Sample Code 259
Event handlers 260
Sample code 260
Embracing eventual consistency 261
Eventual consistency and CQRS 263
Optimizing the read-side 266
Optimizing the write side 267
Concurrency and aggregates 267
Messaging and CQRS 268
Messaging considerations 268
Duplicate messages 268
Lost messages 269
Out-of-order messages 269
Unprocessed messages 269
Event versioning 269
Redundant events 270
New event types 270
Changing existing event definitions 270
Task-based UIs 271
Taking advantage of Windows Azure 272
Scaling out using multiple role instances 273
Implementing an event store using Windows Azure
table storage 273
Persisting events 274
Retrieving events 275
Publishing events 276
Implementing a messaging infrastructure using
the Windows Azure Service Bus 278
A word of warning 279
More information 279
Reference 5: Communicating Between Bounded Contexts 281
Introduction 281
Context maps 281
The anti-corruption layer 281
xiv
Integration with legacy systems 282
Reading the database 282
Generating events from the database 282
Modifying the legacy systems 282
Implications for event sourcing 282
More information 283
Reference 6: A Saga on Sagas 285
Clarifying the terminology 285
Process Manager 286
Messages and CQRS 286
What is a process manager? 286
When should I use a process manager? 290
When should I not use a process manager? 290
Sagas and CQRS 290
More information 290
Reference 7: Technologies Used in the Reference
Implementation 291
Windows Azure Service Bus 291
Queues 292
Topics and Subscriptions 293
Useful API features 294
Reading messages 294
Sending messages 294
Expiring messages 294
Delayed message processing 294
Serializing messages 295
Further information 295
Unity Application Block 296
Further information 296
More information 296
Tales from the Trenches 297
Twilio 297
Product overview 297
Lessons learned 297
Separating reads and writes 297
Designing for high availability 297
Idempotency 298
No-downtime deployments 298
Performance 298
References 299
More information 299
xv
Tales from the Trenches: Lokad Hub 300
Project overview 300
Lessons learned 300
Benefits of DDD 301
Reducing dependencies 301
Using sagas 301
Testing and documentation 301
Migration to ES 301
Using projections 301
Event sourcing 301
Infrastructure 302
References 302
More information 302
Tales from the Trenches: DDD/CQRS for large financial
company 303
Project overview 303
Lessons learned 304
Query performance 304
Commands 304
Working with legacy databases 304
Using an Inversion of Control (IoC) container 304
Key lessons learned 305
More information 305
Tales from the Trenches: Digital Marketing 306
Single Responsibility of Objects 309
More information 309
Tales from the Trenches: TOPAZ Technologies 310
What did we hope to accomplish by using CQRS/ES? 310
What were the biggest challenges and how did we
overcome them? 310
What were the most important lessons learned? 311
With hindsight, what would we have done differently? 311
Further information 311
More information 311
Tales from the Trenches: eMoney Nexus 312
eMoney Nexus: Some CQRS lessons 312
About eMoney & the Nexus 312
System overview 313
The evolution of the system 314
Lessons learned 320
Making it better 321
xvi
Appendix 1: Release Notes 323
System evolution 323
Building and running the sample code (RI) 323
Prerequisites 324
Obtaining the code 325
Creating the databases 325
SQL Express Database 325
Windows Azure SQL Database instance 325
Creating the Settings.xml File 327
Building the RI 327
Build Congurations 328
Release 328
Debug 328
DebugLocal 328
Running the RI 328
Scenario 1. Local Web Server, SQL Event Bus,
SQL Event Store 328
Scenario 2. Local Web Server, Windows Azure
Service Bus, Table Storage Event Store 329
Scenario 3. Compute Emulator, SQL Event Bus,
SQL Event Store 329
Scenario 4. Compute Emulator, Windows Azure
Service Bus, Table Storage Event Store 329
Scenario 5. Windows Azure, Windows Azure
Service Bus, Table Storage Event Store 329
Running the Tests 329
Running the Unit and Integration Tests 329
Running the Acceptance Tests 330
Known issues 330
More information 330
Appendix 2: Migrations 331
Migrating from the V1 to the V2 release 331
Running the migration program to migrate the data 331
If the data migration fails 332
Migrating from the V2 to the V3 Release 333
More information 333
Index 335
xvii
This is another excellent guide from the patterns & practices team—real software engineering with
no comforting illusions taken or offered. This guide provides a detailed journal of the practitioners
implementing a real production system using the CQRS and Event Sourcing patterns, and also high-
lights the tradeoffs and teaches the principles that underlie them. The topics presented are relevant
and useful, especially if you are building highly scalable Windows Azure applications. You’ll be both
challenged and inspired!
—Scott Guthrie, Corporate Vice-President, Azure App Platform, Microsoft
Having participated and co-authored various guides from patterns & practices, the “CQRS Journey
follows the same walkthrough, scenario-based style, but adding even more fresh empirical content.
Its a true testament of a skilled development team without previous CQRS experience, going through
the journey of implementing a complex system and documenting their adventures and lessons learnt
in this diary. If I had to recommend to someone where to start with CQRS, I would definitely point
them to this guide.
—Matias Woloski, CTO, Auth10 LLC
The “CQRS Journey” guide is an excellent resource for developers who want to begin developing a
CQRS system or convert their current system. It’s a true “trial by fire” approach to the concepts and
implementation hurdles that a team would encounter when adopting CQRS. I would recommend
reading it twice as I picked up even more lessons the second time through.
—Dan Piessens, Lead Software Architect, Zywave
I think its a really big step in communication with the developer community. You not only share your
development experience with a broad audience (which is very valuable by itself) but you’re also open
for learning from the community. While working on real projects its difficult to stop, find some time
to structure your knowledge, prepare it in the form understandable for others. It’s very cool that you
found time and resources for such educational effort, I really appreciate this.
—Ksenia Mukhortova, Business Applications Developer, Intel
I’m very excited about A CQRS Journey for a number of reasons. It explores, with an even hand and a
fair mind, a topic where opinions are both diverse and numerous. True to its name, the guide captures
the progression of learning. Conclusions are not simply stated; they arrive as a result of experience.
Additionally, the project embraced a passionate community with a spirit of inclusion and transparency.
The result is friendly-to-read guidance that is both diligent in execution and rigorous in its research.
Christopher Bennage, Software Development Engineer, Microsoft
What other readers are
saying about this guide
xviii
The journey project used Windows Azure SQL Database (backing write & read models), Service Bus
(for reliable messaging), and Tables (for event store). Production-quality, scalable cloud services that
can be provisioned on-demand with a few mouse-clicks (or API calls) can turn some tough infrastruc-
ture problems into trivial ones.
—Bill Wilder, MVP, Independent Consultant
Perhaps the best lessons out of this guidance will be just how easy it is to work with Microsoft now
that they are embracing more community and open source.
—Adam Dymitruk, Systems Architect
The work that patterns & practices is doing here is very important as it is packaging the concepts in
a digestible fashion and helping developers to wade through the ambiguities of CQRS. The real world
experiences captured within the journey project will be invaluable to folks looking at applying CQRS
within their application development
Glenn Block, Senior Program Manager, Microsoft, Windows Azure SDK for Node.js,
Organizer at ALT.NET Seattle Chapter
The p&p team’s dedication and hard work go hand-in-hand with the very high level of competency
present on the team. Their attention to detail, insistence on clarity, and open collaboration with the
community all led to the creation of material representing enormous value to consumers of the guid-
ance. I definitely plan on referencing this material and code in future engagements because I think my
clients will derive many benefits from it–a win-win for everyone!
—Josh Elster, Principal, Liquid Electron
CQRS is a very important pattern, and a tool that any cloud developer should have in his or her tool-
belt. It is particularly well-suited for the cloud since it allows for the implementation of massively
scalable solutions based on simple, common patterns (like queues, event handlers, and view models,
to name a few). Like all patterns, there are several concrete, correct ways of implementing CQRS. A
journey of the type undertaken by Microsofts patterns & practices team is a great way to explore the
different options, tradeoffs, and even possible mistakes one can make along the way, and accelerate
one’s learning of the CQRS pattern.
—Shy Cohen, Principal, Shy Cohen Consulting
patterns & practices assembled many of the active and key people in the CQRS community to join
them on the their journey with CQRS and along the way discovered confusing terminology and con-
cepts that created opportunities for leaders in the community to bring clarity to a broad audience.
The material produced is influenced from the results of building a real world application and ex-
presses the experiences from advisors and the patterns & practices team during the development
process. By request from the community to allow outside contributions, everything has been open
sourced on GitHub. Anyone interested is encouraged to take a look at the guide or implementation.
The patterns & practices team has been very welcoming to anyone who wants to collaborate on
covering additional areas, alternative implementations or further extending what is currently in place.
—Kelly Sommers, Developer
xix
Congratulations on getting to what looks to be nice guidance. I know that the announcement that
p&p was going to embark on this project caused a twitter firestorm but you seem to have come
through it well. I’m a fan of the p&p books and think you’ve done a great job in sharing good prac-
tices with the community.
—Neil Mackenzie, Windows Azure MVP
CQRS is as much about architecture community as it is about concrete patterns—thus the project is
aptly named “CQRS Journey.” The community involvement and engagement in this project is unprec-
edented for Microsoft and reflects the enthusiasm amongst the many (if may say: young) software
architects from across the industry who are rediscovering proven architecture patterns and are recom-
posing them in new ways to solve todays challenges. For me, one takeaway from this project is that
the recipes developed here need to be carefully weighed against their alternatives. As with any soft-
ware architecture approaches that promise easy scalability or evolvability of solutions, the proof will
be in concrete, larger production implementations and how they hold up to changing needs over time.
Thus, the results of this Journey project mark a start and not a finish line.
Clemens Vasters, Principal Technical Lead, Microsoft Corporation
The experiences and conclusions of the p&p team match up very well with our own real-world expe-
riences. Their conclusions in Chapter 8 are spot on. One of the best aspects of this guidance is that
the p&p team exposes more of their thought processes and learning throughout the Journey than
most write-ups that you may read. From arguments between Developer 1 and Developer 2 on the
team, to discussions with experts such as Greg Young and Udi Dahan, to an excellent post-project
review in Chapter 8, the thought process is out there for you to learn from.
Thanks for this great work, guys. I hope you keep this style with your upcoming guidance pieces.
—Jon Wagner, SVP & Chief Architect, eMoney Advisor
The CQRS journey release by patterns & practices provides real world insight into the increasingly
popular CQRS pattern used in distributed systems that rely upon asynchronous, message based ap-
proaches to achieve very large scale. The exploration of the issues the team faced throughout the
implementation of the pattern is extremely useful for organizations considering CQRS, both to de-
termine where the pattern is appropriate for them, and to go into the design and implementation with
a baseline understanding of the complexity it will introduce. I really enjoyed the candor around the
approach taken, the issues encountered, and the early design choices that the team would change in
hindsight. This is a must read for any organization embarking upon CQRS, regardless of what platform
they are using.
Chris Keyser, VP Engineering, CaseNetwork
It is a great resource on tactical and technical aspects of building a distributed system.
—Rinat Abdullin, Technology Leader, Lokad
I’d like to personally thank the team for putting together such a transparent journey throughout this
project. Im very pleased with the final release.
Truong Nguyen, CEO, Nepsoft
Its a good read. Lots to learn from it.
Christian Horsdal Gammelgaard, Lead Software Architect, Mjølner Informatics
Foreword by Greg Young
I started off the new year on January 3rd with a few hour long meeting showing the team at patterns
& practices a bit about Command and Query Responsibility Segregation (CQRS) and Event Sourcing
(ES). Most of the team had previously not been exposed to these ideas. Today is almost exactly six
months later and they have produced a document of over 200 pages of discussions and guidance as
well as a full end to end example hosted in Windows Azure. This is certainly not a small feat.
When the announcement of the project came out, the twitter stream near instantly went nega-
tive as many thought that Microsoft was building a CQRS framework; which was premature from the
community. The process followed similar paths to other patterns & practices projects with a large
advisor board being set up. I believe however that the most interesting part of the process was the
decision to host the work on GitHub and allow pull requests which is an extremely open and transpar-
ent way of communicating during the project.
One of the main benefits for the community as a whole of going through such a process is that
people were forced to refine their vocabularies. There are in the DDD/CQRS/ES communities many
different voices and often times, especially in younger groups, vocabularies will go down divergent paths
leading to fractured community. An example of nebulous terminologies can be seen in the terms ”saga,”
process manager,” and ”workflow”; the community as a whole I believe benefited from the discussions
over defining what it actually is. One of the most interesting conversations brought up for me person-
ally was defining the difference between an Event Store and a Transaction Log as legitimate arguments
can be made that either is a higher level abstraction of the other. This has led not only to many interest-
ing discussions in the community but to a far stricter future definition of what an Event Store is.
”For the things we have to learn before we can do them, we learn by doing them. ~Aristotle
The quote above was the team motto during the project. Many will be looking towards the guidance
presented as being authoritative guidance of how things should be done. This is however not the
optimal way to look at the guidance as presented (though it does contain many bits of good authori-
tative guidance). The main benefit of the guidance is the learning experience that it contains. It is
important to remember that the team came into the ideas presented as non-experienced in CQRS
and they learned in the process of doing. This gives a unique perspective throughout much of the text
where things are learned along the way or are being seen through fresh eyes of someone recently
having learned and attempted to apply the ideas. This perspective has also brought up many interest-
ing conversations within the community. The patterns & practices team deserves credit for digging
deep, facilitating these discussions, and bringing to light various incongruities, confusions and incon-
sistencies as they went along.
xxi
xxii
Keeping in mind the origination point of the team, the most valuable bits in the text that a
reader should focus on aside from general explanations are places where tradeoffs are discussed.
There is an unfortunate tendency to seek authoritative answers that ”things should be done in this
way” when they in fact do not exist. There are many ways to proverbially skin a cat and all have their
pros and cons. The text is quite good at discussing alternative points of view that came up as possible
answers, or that received heavy discussion within the advisor group, these can often be seen in the
developer1/developer 2 discussions.” One such discussion I mentioned previously in defining the
difference between event sourcing and a transaction log. Many of these types of discussions come at
the end of the guidance.
How might things be approached differently? One of my favourite discussions towards the end
of the guidance dealing with performance is the independent realization that messaging is not
equivalent to distribution. This is a very hard lesson for many people to understand and the way that
it comes up rather organically and much like it would on most teams as a performance problem is a
great explanation. I can say 100 times to apply the first law of distributed computing, don’t distribute;
however seeing it from the eyes of a team dealing with a performance problem who has already made
the mistake of equating the two is a very understandable path and a great teaching tool. This section
also contains a smörgåsbord of information and insights in terms of how to build performant applica-
tions in Windows Azure.
Out in the wild, there are plenty of naïve samples of CQRS/ES implementations, which are great
for describing the concepts. There are details and challenges that will not surface till you work on a
complex, real-world production system. The value of the p&p’s sample application is that it uses a
fairly complex domain and the team went through multiple releases and focused on infrastructure
hardening, performance optimizations, dealing with transient faults and versioning, etc. — many
practical issues that you face when implementing CQRS and ES.
As with any project, people may disagree with implementation choices and decisions made. It is
important to remember the scoping of the project. The guidance is not coming from an expert view-
point throughout the process, but that of a group “learning by doing.” The process was and remains
open to contributions, and in fact this version has been reviewed, validated, and guided by experts in
the community. In the spirit of OSS “send a pull request.” This guide can serve as a valuable point to
start discussions, clear up misconceptions, and refine how we explain things, as well as drive improve-
ment both in the guidance itself and in getting consistent viewpoints throughout the community.
In conclusion I think patterns & practices has delivered to the community a valuable service in the
presentation of this guidance. The view point the guidance is written from is both an uncommon and
valuable one. It has also really been a good overall exercise for the community in terms of setting the
bar for what is being discussed and refining of the vocabularies that people speak in. Combine this
with the amount of previously difficult to find Windows Azure guidance and the guidance becomes
quite valuable to someone getting into the ideas.
Greg Young
Preface
Why are we embarking on this journey?
The best way to observe a fish is to become a fish.
Jacques Cousteau
Why we created this guidance now
The Command Query Responsibility Segregation (CQRS) pattern and event sourcing (ES) are cur-
rently generating a great deal of interest from developers and architects who are designing and build-
ing large-scale, distributed systems. There are conference sessions, blogs, articles, and frameworks all
dedicated to the CQRS pattern and to event sourcing, and all explaining how they can help you to
improve the maintainability, testability, scalability, and flexibility of your systems.
However, like anything new, it takes some time before a pattern, approach, or methodology is
fully understood and consistently defined by the community and has useful, practical guidance to help
you to apply or implement it.
This guidance is designed to help you get started with the CQRS pattern and event sourcing. It is
not intended to be the guide to the CQRS pattern and event sourcing, but a guide that describes the
experiences of a development team in implementing the CQRS pattern and event sourcing in a real-
world application. The development team did not work in isolation; they actively sought input from
industry experts and from a wider group of advisors to ensure that the guidance is both detailed and
practical.
The CQRS pattern and event sourcing are not mere simplistic solutions to the problems associ-
ated with large-scale, distributed systems. By providing you with both a working application and
written guidance, we expect you’ll be well prepared to embark on your own CQRS journey.
How is this guidance structured?
There are two closely related parts to this guidance:
• A working reference implementation (RI) sample, which is intended to illustrate many of the
concepts related to the CQRS pattern and event sourcing approaches to developing complex
enterprise applications.
• This written guidance, which is intended to complement the RI by describing how it works,
what decisions were made during its development, and what trade-offs were considered.
xxiii
xxiv
This written guidance is itself split into three distinct sections that you can read independently: a
description of the journey we took as we learned about CQRS, a collection of CQRS reference ma-
terials, and a collection of case studies that describe the experiences other teams have had with the
CQRS pattern. The map in Figure 1 illustrates the relationship between the first two sections: a
journey with some defined stopping points that enables us to explore a space.
F 
A CQRS journey
A CQRS journey
This section is closely related to the RI and the chapters follow the chronology of the project to de-
velop the RI. Each chapter describes relevant features of the domain model, infrastructure elements,
architecture, and user interface (UI) that the team was concerned with during that phase of the
project. Some parts of the system are discussed in several chapters, and this reflects the fact that the
team revisited certain areas during later stages. Each of these chapters discuss how and why particu-
lar CQRS patterns and concepts apply to the design and development of particular bounded contexts,
describe the implementation, and highlight any implications for testing.
xxv
Other chapters look at the big picture. For example, there is a chapter that explains the rationale
for splitting the RI into the bounded contexts we chose, another chapter analyzes the implications of
our approach for versioning the system, and other chapters look at how the different bounded con-
texts in the RI communicate with each other.
This section describes our journey as we learned about CQRS, and how we applied that learn-
ing to the design and implementation of the RI. It is not prescriptive guidance and is not intended
to illustrate the only way to apply the CQRS approach to our RI. We have tried wherever possible
to capture alternative viewpoints through consultation with our advisors and to explain why we
made particular decisions. You may disagree with some of those decisions; please let us know at
cqrsjourney@microsoft.com.
This section of the written guidance makes frequent cross-references to the material in the sec-
ond section for readers who wish to explore any of the concepts or patterns in more detail.
CQRS
The second section of the written guidance is a collection of reference material collated from many
sources. It is not the definitive collection, but should contain enough material to help you to under-
stand the core patterns, concepts, and language of CQRS.
T   
This section of the written guidance is a collection of case studies from other teams that describe
their experiences of implementing the CQRS pattern and event sourcing in the real world. These case
studies are not as detailed as the journey section of the guidance and are intended to give an overview
of these projects and to summarize some of the key lessons learned.
The following is a list of the chapters that comprise both sections of the written guidance:
A CQRS journey
• Chapter 1, “The Contoso Conference Management System,” introduces our sample applica-
tion and our team of (fictional) experts.
• Chapter 2, “Decomposing the Domain,” provides a high-level view of the sample application
and describes the bounded contexts that make up the application.
• Chapter 3, “Orders and Registrations Bounded Context,” introduces our first bounded
context, explores some CQRS concepts, and describes some elements of our infrastructure.
• Chapter 4, “Extending and Enhancing the Orders and Registrations Bounded Context,”
describes adding new features to the bounded context and discusses our testing approach.
• Chapter 5, “Preparing for the V1 Release,” describes adding two new bounded contexts and
handling integration issues between them, and introduces our event-sourcing implementa-
tion. This is our first pseudo-production release.
• Chapter 6, “Versioning Our System,” discusses how to version the system and handle
upgrades with minimal down time.
• Chapter 7, “Adding Resilience and Optimizing Performance,” describes what we did to make
the system more resilient to failure scenarios and how we optimized the performance of the
system. This was the last release of the system in our journey.
• Chapter 8, “Lessons Learned,” collects the key lessons we learned from our journey and
suggests how you might continue the journey.
xxvi
CQRS reference
• Chapter 1, “CQRS in Context,” provides some context for CQRS, especially in relation to the
domain-driven design approach.
• Chapter 2, “Introducing the Command Query Responsibility Segregation Pattern,” provides a
conceptual overview of the CQRS pattern.
• Chapter 3, “Introducing Event Sourcing,” provides a conceptual overview of event sourcing.
• Chapter 4, “A CQRS and ES Deep Dive,” describes the CQRS pattern and event sourcing in
more depth.
• Chapter 5, “Communicating between Bounded Contexts,” describes some options for
communicating between bounded contexts.
• Chapter 6, “A Saga on Sagas,” explains our choice of terminology: process manager instead of
saga. It also describes the role of process managers.
• Chapter 7, “Technologies Used in the Reference Implementation,” provides a brief overview
of some of the other technologies we used, such as the Windows Azure Service Bus.
• Appendix 1, “Release Notes,” contains detailed instructions for downloading, building, and
running the sample application and test suites.
• Appendix 2, “Migrations,” contains instructions for performing the code and data migrations
between the pseudo-production releases of the Contoso Conference Management System.
Tales from the trenches
• Chapter 1, “Twilio,” describes a highly available, cloud-hosted, communications platform.
Although the team who developed this product did not explicitly use CQRS, many of the
architectural concepts they adopted are very closely related to the CQRS pattern.
• Chapter 2, “Lokad Hub,” describes a project that made full use of domain-driven design,
CQRS, and event sourcing in an application designed to run on multiple cloud platforms.
• Chapter 3, “DDD/CQRS for large financial company,” describes a project that made full use
of domain-driven design and CQRS to build a reference application for a large financial
company. It used CQRS to specifically address the issues of performance, scalability, and
reliability.
• Chapter 4, “Digital Marketing,” describes how an existing application was refactored over
time while delivering new features. This project adopted the CQRS pattern for one of its
pieces as the project progressed.
• Chapter 5, “TOPAZ Technologies,” describes a project that used the CQRS pattern and
event sourcing to simplify the development of an off-the-shelf enterprise application.
• Chapter 6, “eMoney Nexus,” describes migration project for an application that used legacy
three-tier architecture to an architecture that used the CQRS pattern and event sourcing.
Many of the conclusions drawn in this project are similar to our own experiences on our
CQRS journey.
S     RI
Before embarking on our journey, we needed to have an outline of the route we planned to take and
an idea of what the final destination should be. We needed to select an appropriate domain for the RI.
We engaged with the community and our advisory board to help us choose a domain that would
enable us to highlight as many of the features and concepts of CQRS as possible. To help us select be-
tween our candidate domains, we used the criteria in the following list. The domain selected should be:
xxvii
• Non-trivial. The domain must be complex enough to exhibit real problems, but at the same
time simple enough for most people to understand without weeks of study. The problems
should involve dealing with temporal data, stale data, receiving out-of-order events, and
versioning. The domain should enable us to illustrate solutions using event sourcing, sagas, and
event merging.
• Collaborative. The domain must contain collaborative elements where multiple actors can
operate simultaneously on shared data.
• End to end. We wanted to be able illustrate the concepts and patterns in action from the
back-end data store through to the user interface. This might include disconnected mobile and
smart clients.
• Cloud friendly. We wanted to have the option of hosting parts of the RI on Windows Azure
and be able to illustrate how you can use CQRS for cloud-hosted applications.
• Large. We wanted to be able to show how our domain can be broken down into multiple
bounded contexts to highlight when to use and when not use CQRS. We also wanted to
illustrate how multiple architectural approaches (CQRS, CQRS/ES, and CRUD) and legacy
systems can co-exist within the same domain. We also wanted to show how multiple develop-
ment teams could carry out work in parallel.
• Easily deployable. The RI needed to be easily deployable so that you can install it and experi-
ment with it as you read this guidance.
As a result, we chose to implement the conference management system that Chapter 1, “Our Domain:
The Contoso Conference Management System,” introduces.
A
Many illustrations in the guidance have arrows. Here is their associated meaning.
F 
Legend for arrows
Event message
Command message
Method call
Flow of data
Object relationship
xxviii
Where to go for more information
There are a number of resources listed in text throughout the book. These resources will provide
additional background, bring you up to speed on various technologies, and so forth. For your conve-
nience, there is a bibliography online that contains all the links so that these resources are just a click
away.
You can find the bibliography on MSDN at: http://msdn.microsoft.com/en-us/library/jj619274.
xxix
The Crew
Captain Ernest Shackleton’s Antarctic expedition recruitment ad (1913) stated:
No fewer than 5000 people replied…
When we embarked on our journey half a
year ago, it felt almost the same. With no
fewer than 70 community members (both ex-
perts and enthusiastic novices) answering the
call for advisory board and offering to volun-
teer their time to help us steer this project!
We have now reached the end of the
journey. These are the members of the devel-
opment team who endured the challenges of
the journey and produced this guide:
Vision and Program Management Grigori Melnik (Microsoft Corporation)
Development Julián Domínguez (Microsoft Corporation), Daniel Cazzulino and Fernando Simon-
azzi (Clarius Consulting)
Testing Mani Subramanian (Microsoft Corporation), Hernan de Lahitte (Digit Factory), and Rathi
Velusamy (Infosys Technologies Ltd.)
Documentation Dominic Betts (Content Master Ltd.), Julián Domínguez, Grigori Melnik, and Mani
Subramanian (Microsoft Corporation), and Fernando Simonazzi (Clarius Consulting)
Graphic Design Alexander Ustinov and Anton Rusecki (JetStyle)
Editing and Production RoAnn Corbisier and Nelly Delgado (Microsoft Corporation), Nancy Mi-
chell (Content Master Ltd.), and Chris Burns (Linda Werner & Associates Inc)
The development team didn’t embark on this journey by themselves and didn’t work in isolation.
We actively sought input from industry experts and from a wider group of advisors to ensure that the
guidance is detailed, practical, and informed by real-world experience. We would like to thank our
advisory board members and the DDD/CQRS community members in general who have accompanied
us on this journey for their active participation, insights, critiques, challenges, and reviews. We have
learned and unlearned many things, we’ve explored and experimented a lot. The journey wasn’t easy
but it was so worth it and we enjoyed it. Thank you for keeping us grounded in the real-world chal-
lenges. Thank you for your ongoing support of our effort. We hope the community will continue
exploring the space, pushing the state of the practice further, and extending the reference implemen-
tation and the guidance.
xxx
Specifically, we’d like to acknowledge the following people who have contributed to the journey
in many different ways:
• Greg Young for your pragmatism, patience with us, continuous mentoring and irreplaceable
advice;
• Udi Dahan for challenging us and offering alternative views on many concepts;
• Clemens Vasters for pushing back on terminology and providing a very valuable perspective from
the distributed database field;
• Kelly Sommers for believing in us and bringing sanity to the community as well as for deep
technical insights;
• Adam Dymitruk for jumpstarting us on git and extending the RI;
• Glenn Block for encouraging us to go all the way with the OSS initiative and for introducing us
to many community members;
• Our GM Lori Brownell and our director Björn Rettig for providing sponsorship of the initiative
and believing in our vision;
• Scott Guthrie for supporting the project and helping amplify the message;
• Josh Elster for exploring and designing the MIL (Messaging Intermediate Language) and pushing
us to make it easier to follow the workflow of messages in code;
• Cesar De la Torre Llorente for helping us spike on the alternatives and bringing up terminological
incongruities between various schools and thought leaders;
• Rinat Abdullin for active participation at the beginning of the project and contributing a case
study;
• Bruno Terkaly and Ricardo Villalobos for exploring the disconnected client scenario that would
integrate with the RI;
• Einar Otto Stangvik for spiking on the Schedule Builder bounded context implementation in
Node.js;
• Mark Seemann for sending the very first pull request focusing on code quality;
• Christopher Bennage for helping us overcome GitHub limitations by creating the pundit review
system and the export-to-Excel script to manage iteration backlog more effectively;
• Bob Brumfield, Eugenio Pace, Carlos Farre, Hanz Zhang, and Rohit Sharma for many insights
especially on the perf and hardening challenges;
• Chris Tavares for putting out the first CQRS experiment at p&p and suggesting valuable scenarios;
• Tim Sharkinian for your perspectives on CQRS and for getting us on the SpecFlow train;
• Jane Sinyagina for helping solicit and process feedback from the advisors;
• Howard Wooten and Thomas Petchel for feedback on the UI style and usability;
• Kelly Leahy for sharing your experience and making us aware of potential pitfalls;
• Dylan Smith for early conversations and support of this project in pre-flight times;
• Evan Cooke, Tim Walton, Alex Dubinkov, Scott Brown, Jon Wagner, and Gabriel N. Schenker for
sharing your experiences and contributing mini-case studies.
We feel honored to be supported by such an incredible group of people.
Thank you!
“I am prepared to go anywhere, provided it be forward.”
David Livingstone
This chapter introduces a fictitious company named Contoso. It describes Contoso’s plans to launch
the Contoso Conference Management System, a new online service that will enable other companies
or individuals to organize and manage their own conferences and events. This chapter describes, at a
high-level, some of the functional and non-functional requirements of the new system, and why
Contoso wants to implement parts of it using the Command Query Responsibility Segregation
(CQRS) pattern and event sourcing (ES). As with any company considering this process, there are
many issues to consider and challenges to be met, particularly because this is the first time Contoso
has used both the CQRS pattern and event sourcing. The chapters that follow show, step by step,
how Contoso designed and built its conference management application.
This chapter also introduces a panel of fictional experts to comment on the development efforts.
The Contoso Corporation
Contoso is a startup ISV company of approximately 20 employees that specializes in developing solu-
tions using Microsoft technologies. The developers at Contoso are knowledgeable about various
Microsoft products and technologies, including the .NET Framework, ASP.NET MVC, and Windows
Azure. Some of the developers have previous experience using the domain-driven design (DDD) ap-
proach, but none of them have used the CQRS pattern previously.
The Conference Management System application is one of the first innovative online services that
Contoso wants to take to market. As a startup, Contoso wants to develop and launch these services
with a minimal investment in hardware and IT personnel. Contoso wants to be quick to market in
order to start growing market share, and cannot afford the time to implement all of the planned
functionality in the first releases. Therefore, it is important that the architecture it adopts can easily
accommodate changes and enhancements with minimal impact on existing users of the system. Con-
toso has chosen to deploy the application on Windows Azure in order to take advantage of its ability
to scale applications as demand grows.
Our Domain:
Conference Management System
The starting point: Where have we come from,
what are we taking, and who is coming with us?
J :
J 
Who is coming with us on the journey?
As mentioned earlier, this guide and the accompanying RI describe a CQRS journey. A panel of experts
will comment on our development efforts as we go. This panel includes a CQRS expert, a software
architect, a developer, a domain expert, an IT Pro, and a business manager. They will all comment from
their own perspectives.
Gary is a CQRS expert. He ensures that a CQRS-based solution will
work for a company and will provide tangible benefits. He is a
cautious person, for good reason.
“Defining the CQRS pattern is easy. Realizing the benefits that implementing the
CQRS pattern can offer is not always so straightforward.”
Jana is a software architect. She plans the overall structure of an
application. Her perspective is both practical and strategic. In other
words, she considers not only what technical approaches are needed
today, but also what direction a company needs to consider for the future.
Jana has worked on projects that used the domain-driven design approach.
“It’s not easy to balance the needs of the company, the users, the IT organization, the
developers, and the technical platforms we rely on.”
Markus is a software developer who is new to the CQRS pattern. He is
analytical, detail-oriented, and methodical. Hes focused on the task at
hand, which is building a great application. He knows that he’s the
person who’s ultimately responsible for the code.
“I don’t care what architecture you want to use for the application; Ill make it work.”
Carlos is the domain expert. He understands all the ins and outs of
conference management. He has worked in a number of organizations that
help people run conferences. He has also worked in a number of different
roles: sales and marketing, conference management, and consultant.
“I want to make sure that the team understands how this business works so that we can
deliver a world-class online conference management system.”
O D: C M S
Poe is an IT professional who’s an expert in deploying and running
applications in the cloud. Poe has a keen interest in practical solutions;
after all, hes the one who gets paged at 3:00 AM when there’s a problem.
“Running complex applications in the cloud involves challenges that are different than
the challenges in managing on-premises applications. I want to make sure our new
conference management system meets our published service-level agreements (SLA).”
Beth is a business manager. She helps companies to plan how their business will
develop. She understands the market that the company operates in, the resources
that the company has available, and the goals of the company. She has both a
strategic view and an interest in the day-to-day operations of the company.
“Organizations face many conflicting demands on their resources. I want to make sure that our
company balances those demands and adopts a business plan that will make us successful in the
medium and long term.”If you have a particular area of interest, look for notes provided by the
specialists whose interests align with yours.
The Contoso Conference Management System
This section describes the Contoso Conference Management System as the team envisaged it at the
start of the journey. The team has not used the CQRS pattern before; therefore, the system that is
delivered at the end of our journey may not match this description exactly because:
• What we learn as we go may impact what we ultimately deliver.
• Because this is a learning journey, it is more difficult to estimate what we can achieve in the
available time.
Overview of the system
Contoso plans to build an online conference management system that will enable its customers to
plan and manage conferences that are held at a physical location. The system will enable Contoso’s
customers to:
• Manage the sale of different seat types for the conference.
• Create a conference and define characteristics of that conference.
The Contoso Conference Management System will be a multi-tenant, cloud-hosted application. Busi-
ness customers will need to register with the system before they can create and manage their confer-
ences.
J 
Selling seats for a conference
The business customer defines the number of seats available for the conference. The business cus-
tomer may also specify events at a conference such as workshops, receptions, and premium sessions
for which attendees must have a separate ticket. The business customer also defines how many seats
are available for these events.
The system manages the sale of seats to ensure that the conference and sub-events are not
oversubscribed. This part of the system will also operate wait-lists so that if other attendees cancel,
their seats can be reallocated.
The system will require that the names of the attendees be associated with the purchased seats
so that an on-site system can print badges for the attendees when they arrive at the conference.
Creating a conference
A business customer can create new conferences and manage information about the conference such
as its name, description, and dates. The business customer can also make a conference visible on the
Contoso Conference Management System website by publishing it, or hide it by unpublishing it.
Additionally, the business customer defines the seat types and available quantity of each seat type
for the conference.
Contoso also plans to enable the business customer to specify the following characteristics of a
conference:
• Whether the paper submission process will require reviewers.
• What the fee structure for paying Contoso will be.
• Who key personnel, such as the program chair and the event planner, will be.
Nonfunctional requirements
Contoso has two major nonfunctional requirements for its conference management system—scal-
ability and flexibility—and it hopes that the CQRS pattern will help it meet them.
Scalability
The conference management system will be hosted in the cloud; one of the reasons Contoso chose a
cloud platform was its scalability and potential for elastic scalability.
Although cloud platforms such as Windows Azure enable you to scale applications by adding (or
removing) role instances, you must still design your application to be scalable. By splitting responsibil-
ity for the applications read and write operations into separate objects, the CQRS pattern allows
Contoso to split those operations into separate Windows Azure roles that can scale independently of
each other. This recognizes the fact that for many applications, the number of read operations vastly
exceeds the number of write operations. This gives Contoso the opportunity to scale the conference
management system more efficiently, and make better use of the Windows Azure role instances it uses.
O D: C M S
Flexibility
The market that the Contoso Conference Management System oper-
ates in is very competitive, and very fast moving. In order to compete,
Contoso must be able to quickly and cost effectively adapt the con-
ference management system to changes in the market. This require-
ment for flexibility breaks down into a number of related aspects:
• Contoso must be able to evolve the system to meet new
requirements and to respond to changes in the market.
• The system must be able to run multiple versions of its software
simultaneously in order to support customers who are in the
middle of a conference and who do not wish to upgrade to a
new version immediately. Other customers may wish to migrate
their existing conference data to a new version of the software
as it becomes available.
• Contoso intends the software to last for at least five years. It
must be able to accommodate significant changes over that
period.
• Contoso does not want the complexity of some parts of the
system to become a barrier to change.
• Contoso would like to be able to use different developers for
different elements of the system, using cheaper developers for
simpler tasks and restricting its use of more expensive and
experienced developers to the more critical aspects of the
system.
Beginning the journey
The next chapter is the start of our CQRS journey. It provides more
information about the Contoso Conference Management System and
describes some of the high-level parts of the system. Subsequent
chapters describe the stages of the journey as Contoso implements
the conference management system.
More information
All links in this book are accessible from the books online bibliogra-
phy available at: http://msdn.microsoft.com/en-us/library/jj619274.
Contoso plans to compete
by being quick to respond
to changes in the market
and to changing customer
requirements. Contoso
must be able to evolve
the system quickly and
painlessly.
This is a big challenge:
keeping the system running
for all our customers while
we perform upgrades with
no down time.
There is some debate in the CQRS community about whether,
in practice, you can use different development teams for
different parts of the CQRS pattern implementation.
Without stones there is no arch.”
Marco Polo
In this chapter, we provide a high-level overview of the Contoso Conference Management System.
The discussion will help you understand the structure of the application, the integration points, and
how the parts of the application relate to each other.
Here we describe this high-level structure in terms borrowed from the domain-driven design
(DDD) approach that Eric Evans describes in his book, Domain-Driven Design: Tackling Complexity in
the Heart of Software (Addison-Wesley Professional, 2003). Although there is no universal consensus
that DDD is a prerequisite for implementing the Command Query Responsibility Segregation (CQRS)
pattern successfully, our team decided to use many of the concepts from the DDD approach, such as
domain, bounded context, and aggregate, in line with common practice within the CQRS community.
Chapter 1, “CQRS in Context,” in the Reference Guide discusses the relationship between the DDD
approach and the CQRS pattern in more detail.
Definitions used in this chapter
Throughout this chapter we use a number of terms, which we’ll define in a moment. For more detail,
and possible alternative definitions, see Chapter 1, “CQRS in Context,” in the Reference Guide.
Domain: The domain refers to the business domain for the Contoso Conference Management
System (the reference implementation). Chapter 1, “Our Domain: The Contoso Conference Manage-
ment System,” provides an overview of this domain.
Decomposing the Domain
Planning the stops.
J :
J 
Bounded context: The term bounded context comes from Eric
Evans’ book. In brief, Evans introduces this concept as a way to de-
compose a large, complex system into more manageable pieces; a
large system is composed of multiple bounded contexts. Each bound-
ed context is the context for its own self-contained domain model,
and has its own ubiquitous language. You can also view a bounded
context as an autonomous business component defining clear consis-
tency boundaries: one bounded context typically communicates with
another bounded context by raising events.
Context map: According to Eric Evans, you should “Describe the
points of contact between the models, outlining explicit translation
for any communication and highlighting any sharing.” This exercise
results in what is called a context map, which serves several purposes
that include providing an overview of the whole system and helping
people to understand the details of how different bounded contexts
interact with each other.
Bounded contexts in the conference management
system
The Orders and Registrations bounded context: Within the orders
and registrations bounded context are the reservations, payment, and
registration items. When a registrant interacts with the system, the
system creates an order to manage the reservations, payment, and
registrations. An order contains one or more order items.
A reservation is a temporary reservation of one or more seats at a
conference. When a registrant begins the ordering process to pur-
chase a number of seats at a conference, the system creates reserva-
tions for that number of seats. Those seats are then unavailable for
other registrants to reserve. The reservations are held for 15 minutes,
during which time the registrant can complete the ordering process
by making a payment for the seats. If the registrant does not pay for
the tickets within 15 minutes, the system deletes the reservation and
the seats become available for other registrants to reserve.
The Conference Management bounded context: Within this
bounded context, a business customer can create new conferences
and manage them. After a business customer creates a new confer-
ence, he can access the details of the conference by using his email
address and conference locator access code. The system generates
the access code when the business customer creates the conference.
When you use the CQRS
pattern, you often use
events to communicate
between bounded contexts.
There are alternative
approaches to integration,
such as sharing data at the
database level.
We discussed making the
period of time that the
system holds reservations
a parameter that a business
customer can adjust for
each conference. This may
be a feature that we add if
we determine that there is
a requirement for this level
of control.
D  D
The business customer can specify the following information about a conference:
• The name, description, and slug (part of the URL used to access the conference).
• The start and end dates of the conference.
• The different types and quotas of seats available at the conference.
Additionally, the business customer can control the visibility of the conference on the public website
by either publishing or unpublishing the conference.
The business customer can also use the conference management website to view a list of orders
and attendees.
The Payments bounded context: The payments bounded context is responsible for managing the
interactions between the conference management system and external payment systems. It forwards
the necessary payment information to the external system and receives an acknowledgement that the
payment was either accepted or rejected. It reports the success or failure of the payment back to the
conference management system.
Initially, the payments bounded context will assume that the business customer has an account
with the third-party payment system (although not necessarily a merchant account), or that the busi-
ness customer will accept payment by invoice.
B   
Although they didn’t make it into the final release of the Contoso Conference Management System,
some work was done on three additional bounded contexts. Members of the community are working
on these and other features, and any out-of-band releases and updates will be announced on the
Project “a CQRS Journey website. If you would like to contribute to these bounded contexts or any
other aspect of the system, visit the Project “a CQRS Journey” website or let us know at cqrsjourney@
microsoft.com.
The Discounts bounded context: This is a bounded context to handle the process of managing
and applying discounts to the purchase of conference seats that would integrate with all three exist-
ing bounded contexts.
The Occasionally Disconnected Conference Management client: This is a bounded context to
handle management of conferences on-site with functionality to handle label printing, recording at-
tendee arrivals, and additional seat sales.
The Submissions And Schedule Management bounded context: This is a bounded context to
handle paper submissions and conference event scheduling written using Node.js.
Note: Wait listing is not implemented in this release, but members of the community are working
on this and other features. Any out-of-band releases and updates will be announced on the Project
“a CQRS Journey” website.
 J 
T     C
C M S
Figure 1 and the table that follows it represent a context map that
shows the relationships between the different bounded contexts
that make up the complete system, and as such it provides a high-
level overview of how the system is put together. Even though this
context map appears to be quite simple, the implementation of these
bounded contexts, and more importantly the interactions between
them, are relatively sophisticated; this enabled us to address a wide
range of issues relating to the CQRS pattern and event sourcing (ES),
and provided a rich source from which to capture many valuable les-
sons learned.
Figure 1 shows the three bounded contexts that make up the
Contoso Conference Management System. The arrows in the diagram
indicate the flow of data as events between them.
F 
Bounded contexts in the Contoso Conference Management System
A frequent comment
about CQRS projects is
that it can be difficult to
understand how all of
the pieces fit together,
especially if there a great
many commands and events
in the system. Often, you
can perform some static
analysis on the code to
determine where events
and commands are handled,
but it is more difficult to
automatically determine
where they originate. At a
high level, a context map
can help you understand
the integration between
the different bounded
contexts and the events
involved. Maintaining
up-to-date documentation
about the commands
and events can provide
more detailed insight.
Additionally, if you have
tests that use commands as
inputs and then check for
events, you can examine
the tests to understand the
expected consequences
of particular commands
(see the section on testing
in Chapter 4, “Extending
and Enhancing the Orders
and Registrations Bounded
Context” for an example of
this style of test).

D  D
The following list provides more information about the arrows in
Figure 1. You can find additional details in the chapters that discuss
the individual bounded contexts.
1. Events that report when conferences have been created,
updated, or published. Events that report when seat types
have been created or updated.
2. Events that report when orders have been created or up-
dated. Events that report when attendees have been assigned
to seats.
3. Requests for a payment to be made.
4. Acknowledgement of the success or failure of the payment.
Why did we choose these bounded contexts?
During the planning stage of the journey, it became clear that these
were the natural divisions in the domain that could each contain their
own, independent domain models. Some of these divisions were eas-
ier to identify than others. For example, it was clear early on that the
conference management bounded context is independent of the re-
mainder of the domain. It has clearly defined responsibilities that re-
late to defining conferences and seat types and clearly defined points
of integration with the rest of the application.
On the other hand, it took some time to realize that the orders and
registrations bounded context is separate from the Payments bounded
context. For example, it was not until the V2 release of the application
that all concepts relating to payments disappeared from the orders and
registrations bounded context when the OrderPaymentConfirmed
event became the OrderConfirmed event.
More practically, from the perspective of the journey, we wanted
a set of bounded contexts that would enable us to release a working
application with some core functionality and that would enable us to
explore a number of different implementation patterns: CQRS,
CQRS/ES, as well as integration with a legacy, CRUD-style bounded
context.
More information
All links in this book are accessible from the books online bibliogra-
phy available at: http://msdn.microsoft.com/en-us/library/jj619274.
Some of the events
that the Conference
Management bounded
context raises are coarse-
grained and contain
multiple fields. Remember
that conference
management is a create,
read, update and delete
(CRUD)-style bounded
context and does
not raise fine-grained
domain-style events. For
more information, see
Chapter5, “Preparing for
the V1 Release.”
We continued to
refine the domain
models right through
the journey as our
understanding of the
domain deepened.
Contoso wants to release a usable application as soon as possible, but
be able to add both planned features and customer-requested features
as they are developed and with no down time for the upgrades.

The Allegator is the same, as the Crocodile, and differs only in Name.”
John Lawson
A description of the bounded context
The Orders and Registrations bounded context is partially responsible for the booking process for
attendees planning to come to a conference. In the Orders and Registrations bounded context, a
person (the registrant) purchases seats at a particular conference. The registrant also assigns names of
attendees to the purchased seats (this is described in Chapter 5, “Preparing for the V1 Release”).
This was the first stop on our CQRS journey, so the team decided to implement a core, but self-
contained part of the system—orders and registrations. The registration process must be as painless
as possible for attendees. The process must enable the business customer to ensure that the maximum
possible number of seats can be booked, and give them the flexibility set the prices for the different
seat types at a conference.
Because this was the first bounded context addressed by the team, we also implemented some
infrastructure elements of the system to support the domain’s functionality. These included command
and event message buses and a persistence mechanism for aggregates.
The Contoso Conference Management System described in this chapter is not the final version of
the system. This guidance describes a journey, so some of the design decisions and implementation
details change later in the journey. These changes are described in subsequent chapters.
Plans for enhancements to this bounded context in some future journey include support for wait
listing, whereby requests for seats are placed on a wait list if there aren’t sufficient seats available, and
enabling the business customer to set various types of discounts for seat types.
Wait listing is not implemented in this release, but members of the community are working on this
and other features. Any out-of-band releases and updates will be announced on the Project “a
CQRS Journey website.
Orders and Registrations
Bounded Context
The first stop on our CQRS journey.
J :
 J 
Working definitions for this chapter
This chapter uses a number of terms that we will define in a moment.
For more detail, and possible alternative definitions, see “A CQRS and
ES Deep Dive” in the Reference Guide.
Command. A command is a request for the system to perform an
action that changes the state of the system. Commands are impera-
tives; MakeSeatReservation is one example. In this bounded context,
commands originate either from the UI as a result of a user initiating
a request, or from a process manager when the process manager is
directing an aggregate to perform an action.
A single recipient processes a command. A command bus trans-
ports commands that command handlers then dispatch to aggregates.
Sending a command is an asynchronous operation with no return
value.
Event. An event, such as OrderConfirmed, describes something
that has happened in the system, typically as a result of a command.
Aggregates in the domain model raise events.
Multiple subscribers can handle a specific event. Aggregates pub-
lish events to an event bus; handlers register for specific types of
events on the event bus and then deliver the event to the subscriber.
In this bounded context, the only subscriber is a process manager.
Process manager. In this bounded context, a process manager is a
class that coordinates the behavior of the aggregates in the domain.
A process manager subscribes to the events that the aggregates raise,
and then follow a simple set of rules to determine which command or
commands to send. The process manager does not contain any busi-
ness logic; it simply contains logic to determine the next command to
send. The process manager is implemented as a state machine, so
when it responds to an event, it can change its internal state in addi-
tion to sending a new command.
Our process manager is an implementation of the Process Man-
ager pattern defined on pages 312 to 321 of the book by Gregor
Hohpe and Bobby Woolf, entitled Enterprise Integration Patterns:
Designing, Building, and Deploying Messaging Solutions (Addison-
Wesley Professional, 2003).
For a discussion of some
possible optimizations
that also involve a slightly
different definition of a
command, see Chapter 6,
Versioning our System.”
It can be difficult for someone new to the code to follow
the flow of commands and events through the system. For
a discussion of a technique that can help, see the section
“Impact on testing” in Chapter 4, “Extending and Enhancing
the Orders and Registrations Bounded Contexts.”

O  R B C
The process manager in this bounded context can receive com-
mands as well as subscribe to events.
The Reference Guide contains additional definitions and explana-
tions of CQRS-related terms.
Domain denitions (ubiquitous language)
The following list defines the key domain-related terms that the team
used during the development of this Orders and Registrations bound-
ed context.
Attendee. An attendee is someone who is entitled to attend a
conference. An Attendee can interact with the system to perform
tasks such as manage his agenda, print his badge, and provide feed-
back after the conference. An attendee could also be a person who
doesn’t pay to attend a conference such as a volunteer, speaker, or
someone with a 100% discount. An attendee may have multiple as-
sociated attendee types (speaker, student, volunteer, track chair, and
so on.)
Registrant. A registrant is a person who interacts with the sys-
tem to place orders and to make payments for those orders. A regis-
trant also creates the registrations associated with an order. A regis-
trant may also be an attendee.
User. A user is a person such as an attendee, registrant, speaker,
or volunteer who is associated with a conference. Each user has a
unique record locator code that the user can use to access user-spe-
cific information in the system. For example, a registrant can use a
record locator code to access her orders, and an attendee can use a
record locator code to access his personalized conference agenda.
Seat assignment. A seat assignment associates an attendee with
a seat in a confirmed order. An order may have one or more seat as-
signments associated with it.
Order. When a registrant interacts with the system, the system
creates an order to manage the reservations, payment, and registra-
tions. An order is confirmed when the registrant has successfully paid
for the order items. An order contains one or more order items.
Order item. An order item represents a seat type and quantity,
and is associated with an order. An order item exists in one of three
states: created, reserved, or rejected. An order item is initially in the
created state. An order item is in the reserved state if the system has
reserved the quantity of seats of the seat type requested by the regis-
trant. An order item is in the rejected state if the system cannot re-
serve the quantity of seats of the seat type requested by the registrant.
The team initially referred
to the process manager
class in the orders bounded
context as a saga. To find
out why we decided to
change the terminology,
see the section “Patterns
and concepts” later in this
chapter.
We intentionally
implemented a record
locator mechanism to
return to a previously
submitted order via the
mechanism. This eliminates
an often annoying
requirement for users to
create an account in the
system and sign in in order
to evaluate its usefulness.
Our customers were
adamant about this.
 J 
Seat. A seat represents the right to be admitted to a conference or to access a specific session at
the conference such as a cocktail party, a tutorial, or a workshop. The business customer may change
the quota of seats for each conference. The business customer may also change the quota of seats for
each session.
Reservation. A reservation is a temporary reservation of one or more seats. The ordering process
creates reservations. When a registrant begins the ordering process, the system makes reservations
for the number of seats requested by the registrant. These seats are then not available for other
registrants to reserve. The reservations are held for n minutes during which the registrant can com-
plete the ordering process by making a payment for those seats. If the registrant does not pay for the
seats within n minutes, the system cancels the reservation and the seats become available to other
registrants to reserve.
Seat availability. Every conference tracks seat availability for each type of seat. Initially, all of the
seats are available to reserve and purchase. When a seat is reserved, the number of available seats of
that type is decremented. If the system cancels the reservation, the number of available seats of that
type is incremented. The business customer defines the initial number of each seat type to be made
available; this is an attribute of a conference. A conference owner may adjust the numbers for the
individual seat types.
Conference site. You can access every conference defined in the system by using a unique URL.
Registrants can begin the ordering process from this site.
Each of the terms defined here was formulated through active discussions between the devel-
opment team and the domain experts. The following is a sample conversation between devel-
opers and domain experts that illustrates how the team arrived at a definition of the term at-
tendee.
Developer 1: Heres an initial stab at a definition for attendee. “An attendee is someone who
has paid to attend a conference. An attendee can interact with the system to perform tasks
such as manage his agenda, print his badge, and provide feedback after the conference.”
Domain Expert 1: Not all attendees will pay to attend the conference. For example, some
conferences will have volunteer helpers, also speakers typically don’t pay. And, there may be
some cases where an attendee gets a 100% discount.
Domain Expert 1: Don’t forget that its not the attendee who pays; thats done by the regis-
trant.
Developer 1: So we need to say that Attendees are people who are authorized to attend a
conference?
Developer 2: We need to be careful about the choice of words here. The term authorized will
make some people think of security and authentication and authorization.
Developer 1: How about entitled?
Domain Expert 1: When the system performs tasks such as printing badges, it will need to
know what type of attendee the badge is for. For example, speaker, volunteer, paid attendee,
and so on.

O  R B C
Developer 1: Now we have this as a definition that captures everything we’ve discussed. An
attendee is someone who is entitled to attend a conference. An attendee can interact with
the system to perform tasks such as manage his agenda, print his badge, and provide feedback
after the conference. An attendee could also be a person who doesn’t pay to attend a confer-
ence such as a volunteer, speaker, or someone with a 100% discount. An attendee may have
multiple associated attendee types (speaker, student, volunteer, track chair, and so on.)
Requirements for creating orders
A registrant is the person who reserves and pays for (orders) seats at a conference. Ordering is a
two-stage process: first, the registrant reserves a number of seats and then pays for the seats to
confirm the reservation. If registrant does not complete the payment, the seat reservations expire
after a fixed period and the system makes the seats available for other registrants to reserve.
Figure 1 shows some of the early UI mockups that the team used to explore the seat-ordering
story.
F 
Ordering UI mockups
 J 
These UI mockups helped the team in several ways, allowing them to:
• Communicate the core team’s vision for the system to the
graphic designers who are on an independent team at a third-
party company.
• Communicate the domain experts knowledge to the developers.
• Refine the definition of terms in the ubiquitous language.
• Explore “what if” questions about alternative scenarios and
approaches.
• Form the basis for the system’s suite of acceptance tests.
Architecture
The application is designed to deploy to Windows Azure. At this
stage in the journey, the application consists of a web role that con-
tains the ASP.NET MVC web application and a worker role that
contains the message handlers and domain objects. The application
uses a WindowsAzure SQL Database instance for data storage, both
on the write side and the read side. The application uses the Win-
dows Azure Service Bus to provide its messaging infrastructure.
While you are exploring and testing the solution, you can run it
locally, either using the Windows Azure compute emulator or by run-
ning the MVC web application directly and running a console applica-
tion that hosts the handlers and domain objects. When you run the
application locally, you can use a local SQL Server Express database
instead of SQL Database, and use a simple messaging infrastructure
implemented in a SQL Server Express database.
For more information about the options for running the applica-
tion, see Appendix 1, “Release Notes.”
Patterns and concepts
The team decided to implement the first bounded context without us-
ing event sourcing in order to keep things simple. However, they did
agree that if they later decided that event sourcing would bring specific
benefits to this bounded context, then they would revisit this decision.
For a description of how event sourcing relates to the CQRS
pattern, see “Introducing Event Sourcing” in the Reference Guide.
One of the important discussions the team had concerned the choice
of aggregates and entities that they would implement. The following
images from the team’s whiteboard illustrate some of their initial
thoughts, and questions about the alternative approaches they could
take with a simple conference seat reservation scenario to try and
understand the pros and cons of alternative approaches.
A frequently cited
advantage of the CQRS
pattern is that it enables
you to scale the read
side and write side of the
application independently
to support the different
usage patterns. In this
bounded context,
however, the number of
read operations from the
UI is not likely to hugely
out-number the write
operations: this bounded
context focuses on
registrants creating orders.
Therefore, the read side and
the write side are deployed
to the same Windows Azure
worker role rather than
to two separate worker
roles that could be scaled
independently.
A value I think developers
would benefit greatly from
recognizing is the de-emphasis
on the means and methods for
persistence of objects in terms
of relational storage. Teach
them to avoid modeling the
domain as if it was a rela-
tional store, and I think it will
be easier to introduce and
understand both domain-
driven design (DDD) and
CQRS.”
—Josh Elster, CQRS Advisors
Mail List

O  R B C
This scenario considers what happens when a registrant tries to book several seats at a confer-
ence. The system must:
• Check that sufficient seats are available.
• Record details of the registration.
• Update the total number of seats booked for the conference.
We deliberately kept the scenario simple to avoid distractions while the team examines the
alternatives. These examples do not illustrate the final implementation of this bounded context.
The first approach considered by the team, shown in Figure 2, uses two separate aggregates.
These diagrams deliberately exclude details of how the
system delivers commands and events through command
and event handlers. The diagrams focus on the logical
relationships between the aggregates in the domain.
F 
Approach 1: Two separate aggregates
 J 
The numbers in the diagram correspond to the following steps:
1. The UI sends a command to register attendees X and Y for
conference 157. The command is routed to a new Order
aggregate.
2. The Order aggregate raises an event that reports that an
order has been created. The event is routed to the Seats-
Availability aggregate.
3. The SeatsAvailability aggregate with an ID of 157 is re-
hydrated from the data store.
4. The SeatsAvailability aggregate updates its total number of
seats booked.
5. The updated version of the SeatsAvailability aggregate is
persisted to the data store.
6. The new Order aggregate, with an ID of 4239, is persisted to
the data store.
You could consider using the Memento pattern to
handle the persistence and rehydration.
The term rehydration
refers to the process of
deserializing the aggregate
instance from a data store.

O  R B C
The second approach considered by the team, shown in Figure 3, uses a single aggregate in place of two.
F 
Approach 2: A single aggregate
The numbers in the diagram correspond to the following steps:
1. The UI sends a command to register Attendees X and Y for conference 157. The command is
routed to the Conference aggregate with an ID of 157.
2. The Conference aggregate with an ID of 157 is rehydrated from the data store.
3. The Order entity validates the booking (it queries the SeatsAvailability entity to see if there
are enough seats left), and then invokes the method to update the number of seats booked
on the Conference entity.
4. The SeatsAvailability entity updates its total number of seats booked.
5. The updated version of the Conference aggregate is persisted to the data store.
 J 
The third approach considered by the team, shown in Figure 4, uses a process manager to coordinate
the interaction between two aggregates.
F 
Approach 3: Using a process manager
The numbers in the diagram correspond to the following steps:
1. The UI sends a command to register Attendees X and Y for conference 157. The command is
routed to a new Order aggregate.
2. The new Order aggregate, with an ID of 4239, is persisted to the data store.
3. The Order aggregate raises an event that is handled by the RegistrationProcessManager
class.

O  R B C
4. The RegistrationProcessManager class determines that a
command should be sent to the SeatsAvailability aggregate
with an ID of 157.
5. The SeatsAvailability aggregate is rehydrated from the data
store.
6. The total number of seats booked is updated in the Seats-
Availability aggregate and it is persisted to the data store.
For more information about process managers and sagas, see Chapter
6, “A Saga on Sagas” in the Reference Guide.
The team identified the following questions about these ap-
proaches:
• Where does the validation that there are sufficient seats for the
registration take place: in the Order or SeatsAvailability
aggregate?
• Where are the transaction boundaries?
• How does this model deal with concurrency issues when
multiple registrants try to place orders simultaneously?
• What are the aggregate roots?
The following sections discuss these questions in relation to the three
approaches considered by the team.
V
Before a registrant can reserve a seat, the system must check that
there are enough seats available. Although logic in the UI can attempt
to verify that there are sufficient seats available before it sends a
command, the business logic in the domain must also perform the
check; this is because the state may change between the time the UI
performs the validation and the time that the system delivers the
command to the aggregate in the domain.
Process manager or saga?
Initially the team referred to
the RegistrationProcess-
Manager class as a saga.
However, after they
reviewed the original
definition of a saga from
the paper “Sagas” by
Hector Garcia-Molina
and Kenneth Salem, they
revised their decision. The
key reasons for this are that
the reservation process
does not include explicit
compensation steps,
and does not need to be
represented as a long-lived
transaction.
When we talk about UI
validation here, we are
talking about validation that
the Model-View Controller
(MVC) controller performs,
not the browser.
 J 
In the first model, the validation must take place in either the
Order or SeatsAvailability aggregate. If it is the former, the Order
aggregate must discover the current seat availability from the Seats-
Availability aggregate before the reservation is made and before it
raises the event. If it is the latter, the SeatsAvailability aggregate
must somehow notify the Order aggregate that it cannot reserve the
seats, and that the Order aggregate must undo (or compensate for)
any work that it has completed so far.
The second model behaves similarly, except that it is Order and
SeatsAvailability entities cooperating within a Conference aggregate.
In the third model, with the process manager, the aggregates ex-
change messages through the process manager about whether the
registrant can make the reservation at the current time.
All three models require entities to communicate about the vali-
dation process, but the third model with the process manager appears
more complex than the other two.
T 
An aggregate, in the DDD approach, represents a consistency bound-
ary. Therefore, the first model with two aggregates, and the third
model with two aggregates and a process manager will involve two
transactions: one when the system persists the new Order aggregate
and one when the system persists the updated SeatsAvailability ag-
gregate.
The term consistency boundary refers to a boundary within which
you can assume that all the elements remain consistent with each
other all the time.
To ensure the consistency of the system when a registrant creates an
order, both transactions must succeed. To guarantee this, we must
take steps to ensure that the system is eventually consistent by ensur-
ing that the infrastructure reliably delivers messages to aggregates.
In the second approach, which uses a single aggregate, we will
only have a single transaction when a registrant makes an order. This
appears to be the simplest approach of the three.
Undo is just one of many
compensating actions
that occur in real life. The
compensating actions could
even be outside of the
system implementation and
involve human actors: for
example, a Contoso clerk or
the business customer calls
the registrant to tell them
that an error was made and
that they should ignore the
last confirmation email they
received from the Contoso
system.

O  R B C
C
The registration process takes place in a multi-user environment where many registrants could at-
tempt to purchase seats simultaneously. The team decided to use the Reservation pattern to address
the concurrency issues in the registration process. In this scenario, this means that a registrant ini-
tially reserves seats (which are then unavailable to other registrants); if the registrant completes the
payment within a timeout period, the system retains the reservation; otherwise the system cancels
the reservation.
This reservation system introduces the need for additional message types; for example, an event
to report that a registrant has made a payment, or report that a timeout has occurred.
This timeout also requires the system to incorporate a timer somewhere to track when reserva-
tions expire.
Modeling this complex behavior with sequences of messages and the requirement for a timer is
best done using a process manager.
A  
In the two models that have the Order aggregate and the SeatsAvailability aggregate, the team
easily identified the entities that make up the aggregate, and the aggregate root. The choice is not so
clear in the model with a single aggregate: it does not seem natural to access orders through a Seats-
Availability entity, or to access the seat availability through an Order entity. Creating a new entity
to act as an aggregate root seems unnecessary.
The team decided on the model that incorporated a process manager because this offers the best
way to handle the concurrency requirements in this bounded context.
Implementation details
This section describes some of the significant features of the Orders and Registrations bounded
context implementation. You may find it useful to have a copy of the code so you can follow along.
You can download it from the Download center, or check the evolution of the code in the repository
on github: mspnp/cqrs-journey-code.
Do not expect the code samples to match the code in the reference implementation exactly. This
chapter describes a step in the CQRS journey, the implementation may well change as we learn
more and refactor the code.
 J 
H-
As we described in the previous section, the team initially decided to implement the reservations
story in the conference management system using the CQRS pattern but without using event sourc-
ing. Figure 5 shows the key elements of the implementation: an MVC web application, a data store
implemented using a Windows Azure SQL Database instance, the read and write models, and some
infrastructure components.
We’ll describe what goes on inside the read and write models later in this section.
F 
High-level architecture of the registrations bounded context

O  R B C
The following sections relate to the numbers in Figure 5 and provide more detail about these
elements of the architecture.
1. Querying the read model
The ConferenceController class includes an action named Display that creates a view that contains
information about a particular conference. This controller class queries the read model using the
following code:
public ActionResult Display(string conferenceCode)
{
var conference = this.GetConference(conferenceCode);
return View(conference);
}
private Conference.Web.Public.Models.Conference GetConference(string conferenceCode)
{
var repo = this.repositoryFactory();
using (repo as IDisposable)
{
var conference = repo.Query<Conference>()
.First(c => c.Code == conferenceCode);
var conferenceModel =
new Conference.Web.Public.Models.Conference
{
Code = conference.Code,
Name = conference.Name,
Description = conference.Description
};
return conferenceModel;
}
}
The read model retrieves the information from the data store and returns it to the controller using a
data transfer object (DTO) class.
 J 
2. Issuing commands
The web application sends commands to the write model through a command bus. This command bus
is an infrastructure element that provides reliable messaging. In this scenario, the bus delivers mes-
sages asynchronously and once only to a single recipient.
The RegistrationController class can send a RegisterToConference command to the write
model in response to user interaction. This command sends a request to register one or more seats at
the conference. The RegistrationController class then polls the read model to discover whether the
registration request succeeded. See the section “6. Polling the Read Model” below for more details.
The following code sample shows how the RegistrationController sends a RegisterToConference
command:
var viewModel = this.UpdateViewModel(conferenceCode, contentModel);
var command =
new RegisterToConference
{
OrderId = viewModel.Id,
ConferenceId = viewModel.ConferenceId,
Seats = viewModel.Items.Select(x =>
new RegisterToConference.Seat
{
SeatTypeId = x.SeatTypeId,
Quantity = x.Quantity
}).ToList()
};
this.commandBus.Send(command);
All of the commands are sent asynchronously and do not expect return values.
3. Handling commands
Command handlers register with the command bus; the command bus can then forward commands
to the correct handler.
The OrderCommandHandler class handles the RegisterToConference command sent from the
UI. Typically, the handler is responsible for initiating any business logic in the domain and for persist-
ing any state changes to the data store.
The following code sample shows how the OrderCommandHandler class handles the Register-
ToConference command:

O  R B C
public void Handle(RegisterToConference command)
{
var repository = this.repositoryFactory();
using (repository as IDisposable)
{
var seats = command.Seats
.Select(t => new OrderItem(t.SeatTypeId, t.Quantity))
.ToList();
var order = new Order(
command.OrderId,
Guid.NewGuid(),
command.ConferenceId,
seats);
repository.Save(order);
}
}
4. Initiating business logic in the domain
In the previous code sample, the OrderCommandHandler class creates a new Order instance. The
Order entity is an aggregate root, and its constructor contains code to initiate the domain logic. See
the section “Inside the Write Model” below for more details of what actions this aggregate root
performs.
5. Persisting the changes
In the previous code sample, the handler persists the new Order aggregate by calling the Save
method in the repository class. This Save method also publishes any events raised by the Order ag-
gregate on the command bus.
6. Polling the read model
To provide feedback to the user, the UI must have a way to check whether the RegisterToConference
command succeeded. Like all commands in the system, this command executes asynchronously and
does not return a result. The UI queries the read model to check whether the command succeeded.
The following code sample shows the initial implementation where the RegistrationController
class polls the read model until either the system creates the order or a timeout occurs. The Wait-
UntilUpdated method polls the read-model until it finds either that the order has been persisted or
it times out.
 J 
[HttpPost]
public ActionResult StartRegistration(string conferenceCode,
OrderViewModel contentModel)
{
...
this.commandBus.Send(command);
var draftOrder = this.WaitUntilUpdated(viewModel.Id);
if (draftOrder != null)
{
if (draftOrder.State == "Booked")
{
return RedirectToAction(
"SpecifyPaymentDetails",
new { conferenceCode = conferenceCode, orderId = viewModel.Id });
}
else if (draftOrder.State == "Rejected")
{
return View("ReservationRejected", viewModel);
}
}
return View("ReservationUnknown", viewModel);
}
The team later replaced this mechanism for checking whether the system saves the order with an
implementation of the Post-Redirect-Get pattern. The following code sample shows the new version
of the StartRegistration action method.
For more information about the Post-Redirect-Get pattern see the article Post/Redirect/Get on
Wikipedia.

O  R B C
[HttpPost]
public ActionResult StartRegistration(string conferenceCode,
OrderViewModel contentModel)
{
...
this.commandBus.Send(command);
return RedirectToAction(
"SpecifyRegistrantDetails",
new { conferenceCode = conferenceCode, orderId = command.Id });
}
The action method now redirects to the SpecifyRegistrantDetails view immediately after it sends
the command. The following code sample shows how the SpecifyRegistrantDetails action polls for
the order in the repository before returning a view.
[HttpGet]
public ActionResult SpecifyRegistrantDetails(string conferenceCode, Guid orderId)
{
var draftOrder = this.WaitUntilUpdated(orderId);
...
}
The advantages of this second approach, using the Post-Redirect-Get pattern instead of in the
StartRegistration post action are that it works better with the browsers forward and back naviga-
tion buttons, and that it gives the infrastructure more time to process the command before the
MVC controller starts polling.
I 
Aggregates
The following code sample shows the Order aggregate.
public class Order : IAggregateRoot, IEventPublisher
{
public static class States
{
public const int Created = 0;
public const int Booked = 1;
public const int Rejected = 2;
public const int Conrmed = 3;
}
 J 
private List<IEvent> events = new List<IEvent>();
...
public Guid Id { get; private set; }
public Guid UserId { get; private set; }
public Guid ConferenceId { get; private set; }
public virtual ObservableCollection<TicketOrderLine> Lines { get; private set; }
public int State { get; private set; }
public IEnumerable<Ievent> Events
{
get { return this.events; }
}
public void MarkAsBooked()
{
if (this.State != States.Created)
throw new InvalidOperationException();
this.State = States.Booked;
}
public void Reject()
{
if (this.State != States.Created)
throw new InvalidOperationException();
this.State = States.Rejected;
}
}

O  R B C
Notice how the properties of the class are not virtual. In the original version of this class, the proper-
ties Id, UserId, ConferenceId, and State were all marked as virtual. The following conversation be-
tween two developers explores this decision.
Developer 1: Im really convinced you should not make the property virtual, except if required
by the object-relational mapping (ORM) layer. If this is just for testing purposes, entities and ag-
gregate roots should never be tested using mocking. If you need mocking to test your entities,
this is a clear smell that something is wrong in the design.
Developer 2: I prefer to be open and extensible by default. You never know what needs may
arise in the future, and making things virtual is hardly a cost. This is certainly controversial and a
bit non-standard in .NET, but I think its OK. We may only need virtuals on lazy-loaded collec-
tions.
Developer 1: Since CQRS usually makes the need for lazy load vanish, you should not need it
either. This leads to even simpler code.
Developer 2: CQRS does not dictate usage of event sourcing (ES), so if you’re using an aggre-
gate root that contains an object graph, you’d need that anyway, right?
Developer 1: This is not about ES, its about DDD. When your aggregate boundaries are right,
you don’t need delay loading.
Developer 2: To be clear, the aggregate boundary is here to group things that should change to-
gether for reasons of consistency. A lazy load would indicate that things that have been grouped
together don’t really need this grouping.
Developer 1: I agree. I have found that lazy-loading in the command side means I have it mod-
eled wrong. If I don’t need the value in the command side, then it shouldn’t be there. In addition,
I dislike virtuals unless they have an intended purpose (or some artificial requirement from an
object-relational mapping (ORM) tool). In my opinion, it violates the Open-Closed principle: you
have opened yourself up for modification in a variety of ways that may or may not be intended
and where the repercussions might not be immediately discoverable, if at all.
Developer 2: Our Order aggregate in the model has a list of Order Items. Surely we don’t need
to load the lines to mark it as Booked? Do we have it modeled wrong there?
Developer 1: Is the list of Order Items that long? If it is, the modeling may be wrong because
you don’t necessarily need transactionality at that level. Often, doing a late round trip to get and
updated Order Items can be more costly that loading them up front: you should evaluate the
usual size of the collection and do some performance measurement. Make it simple first, opti-
mize if needed.
Thanks to Jérémie Chassaing and Craig Wilson
 J 
Aggregates and process managers
Figure 6 shows the entities that exist in the write-side model. There are two aggregates, Order and
SeatsAvailability, each one containing multiple entity types. Also there is a RegistrationProcess-
Manager class to manage the interaction between the aggregates.
The table in the Figure 6 shows how the process manager behaves given a current state and a
particular type of incoming message.

O  R B C
F 
Domain objects in the write model
The process of registering for a conference begins when the UI sends a RegisterToConference com-
mand. The infrastructure delivers this command to the Order aggregate. The result of this command
is that the system creates a new Order instance, and that the new Order instance raises an Order-
Placed event. The following code sample from the constructor in the Order class shows this happen-
ing. Notice how the system uses GUIDs to identify the different entities.
 J 
public Order(Guid id, Guid userId, Guid conferenceId, IEnumerable<OrderItem> lines)
{
this.Id = id;
this.UserId = userId;
this.ConferenceId = conferenceId;
this.Lines = new ObservableCollection<OrderItem>(items);
this.events.Add(
new OrderPlaced
{
OrderId = this.Id,
ConferenceId = this.ConferenceId,
UserId = this.UserId,
Seats = this.Lines.Select(x =>
new OrderPlaced.Seat
{
SeatTypeId = x.SeatTypeId,
Quantity = x.Quantity
}).ToArray()
});
}
To see how the infrastructure elements deliver commands and events, see Figure 7.
The system creates a new RegistrationProcessManager instance to manage the new order. The
following code sample from the RegistrationProcessManager class shows how the process manager
handles the event.

O  R B C
public void Handle(OrderPlaced message)
{
if (this.State == ProcessState.NotStarted)
{
this.OrderId = message.OrderId;
this.ReservationId = Guid.NewGuid();
this.State = ProcessState.AwaitingReservationConrmation;
this.AddCommand(
new MakeSeatReservation
{
ConferenceId = message.ConferenceId,
ReservationId = this.ReservationId,
NumberOfSeats = message.Items.Sum(x => x.Quantity)
});
}
else
{
throw new InvalidOperationException();
}
}
The code sample shows how the process manager changes its state
and sends a new MakeSeatReservation command that the Seats-
Availability aggregate handles. The code sample also illustrates how
the process manager is implemented as a state machine that receives
messages, changes its state, and sends new messages.
When the SeatsAvailability aggregate receives a MakeReservation
command, it makes a reservation if there are enough available seats. The
following code sample shows how the SeatsAvailability class raises dif-
ferent events depending on whether or not there are sufficient seats.
Notice how we generate
a new globally unique
identifier (GUID) to identify
the new reservation.
We use these GUIDs to
correlate messages to the
correct process manager
and aggregate instances.
 J 
public void MakeReservation(Guid reservationId, int numberOfSeats)
{
if (numberOfSeats > this.RemainingSeats)
{
this.events.Add(new ReservationRejected
{
ReservationId = reservationId,
ConferenceId = this.Id
});
}
else
{
this.PendingReservations.Add(new Reservation(reservationId, numberOfSeats));
this.RemainingSeats -= numberOfSeats;
this.events.Add(new ReservationAccepted
{
ReservationId = reservationId,
ConferenceId = this.Id
});
}
}
The RegistrationProcessManager class handles the ReservationAccepted and ReservationRejected
events. This reservation is a temporary reservation for seats to give the user the opportunity to make
a payment. The process manager is responsible for releasing the reservation when either the purchase
is complete, or the reservation timeout period expires. The following code sample shows how the
process manager handles these two messages.
public void Handle(ReservationAccepted message)
{
if (this.State == ProcessState.AwaitingReservationConrmation)
{
this.State = ProcessState.AwaitingPayment;
this.AddCommand(new MarkOrderAsBooked { OrderId = this.OrderId });
this.commands.Add(
new Envelope<ICommand>(
new ExpireOrder
{
OrderId = this.OrderId,
ConferenceId = message.ConferenceId
})

O  R B C
{
Delay = TimeSpan.FromMinutes(15),
});
}
else
{
throw new InvalidOperationException();
}
}
public void Handle(ReservationRejected message)
{
if (this.State == ProcessState.AwaitingReservationConrmation)
{
this.State = ProcessState.Completed;
this.AddCommand(new RejectOrder { OrderId = this.OrderId });
}
else
{
throw new InvalidOperationException();
}
}
If the reservation is accepted, the process manager starts a timer run-
ning by sending an ExpireOrder command to itself, and sends a Mark-
OrderAsBooked command to the Order aggregate. Otherwise, it
sends a ReservationRejected message back to the Order aggregate.
The previous code sample shows how the process manager sends
the ExpireOrder command. The infrastructure is responsible for
holding the message in a queue for the delay of fifteen minutes.
You can examine the code in the Order, SeatsAvailability, and
RegistrationProcessManager classes to see how the other message
handlers are implemented. They all follow the same pattern: receive a
message, perform some logic, and send a message.
The code samples shown in this chapter are from an early
version of the conference management system. The next chapter
shows how the design and implementation evolved as the team
explored the domain and learned more about the CQRS pattern.
 J 
Infrastructure
The sequence diagram in Figure 7 shows how the infrastructure elements interact with the domain
objects to deliver messages.
F 
Infrastructure sequence diagram
A typical interaction begins when an MVC controller in the UI sends a message using the command
bus. The message sender invokes the Send method on the command bus asynchronously. The com-
mand bus then stores the message until the message recipient retrieves the message and forwards it
to the appropriate handler. The system includes a number of command handlers that register with the
command bus to handle specific types of commands. For example, the OrderCommandHandler class
defines handler methods for the RegisterToConference, MarkOrderAsBooked, and RejectOrder
commands. The following code sample shows the handler method for the MarkOrderAsBooked
command. Handler methods are responsible for locating the correct aggregate instance, calling meth-
ods on that instance, and then saving that instance.

O  R B C
public void Handle(MarkOrderAsBooked command)
{
var repository = this.repositoryFactory();
using (repository as IDisposable)
{
var order = repository.Find<Order>(command.OrderId);
if (order != null)
{
order.MarkAsBooked();
repository.Save(order);
}
}
}
The team later discovered
an issue with this when
they tried to use Windows
Azure Service Bus as the
messaging infrastructure.
Windows Azure Service
Bus does not support
distributed transactions
with databases. For a
discussion of this issue, see
Chapter 5, “Preparing for
the V1 Release.”
The class that implements the IRepository interface is responsible for
persisting the aggregate and publishing any events raised by the ag-
gregate on the event bus, all as part of a transaction.
The only event subscriber in the reservations bounded context is
the RegistrationProcessManager class. Its router subscribes to the
event bus to handle specific events, as shown in the following code
sample from the RegistrationProcessManager class.
We use the term handler to refer to the classes that handle
commands and events and forward them to aggregate instances,
and the term router to refer to the classes that handle events and
commands and forward them to process manager instances.
 J 
public void Handle(ReservationAccepted @event)
{
var repo = this.repositoryFactory.Invoke();
using (repo as IDisposable)
{
lock (lockObject)
{
var process = repo.Find<RegistrationProcessManager>(@event.ReservationId);
process.Handle(@event);
repo.Save(process);
}
}
}
Typically, an event handler method loads a process manager instance,
passes the event to the process manager, and then persists the pro-
cess manager instance. In this case, the IRepository instance is re-
sponsible for persisting the process manager instance and for sending
any commands from the process manager instance to the command
bus.
U  W A S B
To transport command and event messages, the team decided to use
the Windows Azure Service Bus to provide the low-level messaging
infrastructure. This section describes how the system uses the Win-
dows Azure Service Bus and some of the alternatives and trade-offs
the team considered during the design phase.
Figure 8 shows how both command and event messages flow
through the system. MVC controllers in the UI and domain objects use
CommandBus and EventBus instances to send BrokeredMessage
messages to one of the two topics in the Windows Azure Service Bus.
To receive messages, the handler classes register with the Command-
Processor and EventProcessor instances that retrieve messages from
the topics by using the SubscriptionReceiver class. The Command-
Processor class determines which single handler should receive a com-
mand message; the EventProcessor class determines which handlers
should receive an event message. The handler instances are responsible
for invoking methods on the domain objects.
A Windows Azure Service Bus topic can have multiple
subscribers. The Windows Azure Service Bus delivers messages
sent to a topic to all its subscribers. Therefore, one message can
have multiple recipients.
The team at Contoso
decided to use the
Windows Azure Service
Bus because it offers out-
of-the-box support for the
messaging scenarios in the
conference management
system. This minimizes
the amount of code
that the team needs to
write, and provides for a
robust, scalable messaging
infrastructure. The team
plans to use features such
as duplicate message
detection and guaranteed
message ordering. For a
summary of the differences
between Windows Azure
Service Bus and Windows
Azure Queues, see
Windows Azure Queues
and Windows Azure Service
Bus Queues - Compared and
Contrasted” on MSDN.

O  R B C
F 
Message flows through a Windows Azure Service Bus topic
In the initial implementation, the CommandBus and EventBus classes are very similar. The only dif-
ference between the Send method and the Publish method is that the Send method expects the
message to be wrapped in an Envelope class. The Envelope class enables the sender to specify a time
delay for the message delivery.
Events can have multiple recipients. In the example shown in Figure 8, the ReservationRejected
event is sent to the RegistrationProcessManager, the WaitListProcessManager, and one other
destination. The EventProcessor class identifies the list of handlers to receive the event by examining
its list of registered handlers.
A command has only one recipient. In Figure 8, the MakeSeatReservation is sent to the Seats-
Availability aggregate. There is just a single handler registered for this subscription. The Command-
Processor class identifies the handler to receive the command by examining its list of registered
handlers.
 J 
This implementation gives rise to a number of questions:
• How do you limit delivery of a command to a single recipi-
ent?
• Why have separate CommandBus and EventBus classes if
they are so similar?
• How scalable is this approach?
• How robust is this approach?
• What is the granularity of a topic and a subscription?
• How are commands and events serialized?
The following sections discuss these questions.
Delivering a command to a single recipient
This discussion assumes you that you have a basic understanding of
the differences between Windows Azure Service Bus queues and
topics. For an introduction to Windows Azure Service Bus, see “Tech-
nologies Used in the Reference Implementation” in the Reference
Guide.
With the implementation shown in Figure 8, two things are nec-
essary to ensure that a single handler handles a command message.
First, there should only be a single subscription to the conference/
commands topic in Windows Azure Service Bus; remember that a
Windows Azure Service Bus topic may have multiple subscribers.
Second, the CommandProcessor should invoke a single handler for
each command message that it receives. There is no way in Windows
Azure Service Bus to restrict a topic to a single subscription; there-
fore, the developers must be careful to create just a single subscrip-
tion on a topic that is delivering commands.
It is possible to have multiple SubscriptionReceiver instances
running, perhaps in multiple worker role instances. If multiple
SubscriptionReceiver instances can receive messages from the
same topic subscription, then the first one to call the Receive
method on the SubscriptionClient object will get and handle the
command.
An alternative approach is to use a Windows Azure Service Bus queue
in place of a topic for delivering command messages. Windows Azure
Service Bus queues differ from topics in that they are designed to
deliver messages to a single recipient instead of to multiple recipients
through multiple subscriptions. The developers plan to evaluate this
option in more detail with the intention of implementing this ap-
proach later in the project.
A separate issue is to ensure
that the handler retrieves
commands from the topic
and processes them only
once. You must ensure
either that the command
is idempotent, or that
the system guarantees to
process the command only
once. The team will address
this issue in a later stage of
the journey. See Chapter7,
Adding Resilience and
Optimizing Performance”
for more information.

O  R B C
The following code sample from the SubscriptionReceiver class shows how it receives a message
from the topic subscription.
private SubscriptionClient client;
...
private void ReceiveMessages(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
BrokeredMessage message = null;
try
{
message = this.receiveRetryPolicy
.ExecuteAction(this.DoReceiveMessage);
}
catch (Exception e)
{
Trace.TraceError(
"An unrecoverable error occurred while trying to receive" +
"a new message:\r\n{0}",
e);
throw;
}
try
{
if (message == null)
{
Thread.Sleep(100);
continue;
}
this.MessageReceived(this, new BrokeredMessageEventArgs(message));
}
nally
{
if (message != null)
{
message.Dispose();
}
 J 
}
}
}
protected virtual BrokeredMessage DoReceiveMessage()
{
return this.client.Receive(TimeSpan.FromSeconds(10));
}
The Windows Azure Service Bus SubscriptionClient class uses a
peek/lock technique to retrieve a message from a subscription. In the
code sample, the Receive method locks the message on the subscrip-
tion. While the message is locked, other clients cannot see it. The
Receive method then tries to process the message. If the client pro-
cesses the message successfully, it calls the Complete method; this
deletes the message from the subscription. Otherwise, if the client
fails to process the message successfully, it calls the Abandon method;
this releases the lock on the message and the same, or a different
client can then receive it. If the client does not call either the Com-
plete or Abandon methods within a fixed time, the lock on the mes-
sage is released.
The MessageReceived event passes a reference to the
SubscriptionReceiver instance so that the handler can call either
the Complete or Abandon methods when it processes the
message.
The following code sample from the MessageProcessor class shows
how to call the Complete and Abandon methods using the
BrokeredMessage instance passed as a parameter to the Message-
Received event.
private void OnMessageReceived(object sender, BrokeredMessageEventArgs args)
{
var message = args.Message;
object payload;
using (var stream = message.GetBody<Stream>())
using (var reader = new StreamReader(stream))
{
This code sample shows
how the system uses the
Transient Fault Handling
Applicaon Block to retrieve
messages reliably from the
topic.

O  R B C
payload = this.serializer.Deserialize(reader);
}
try
{
...
ProcessMessage(payload);
...
}
catch (Exception e)
{
if (args.Message.DeliveryCount > MaxProcessingRetries)
{
Trace.TraceWarning(
"An error occurred while processing a new message and" +
"will be dead-lettered:\r\n{0}",
e);
message.SafeDeadLetter(e.Message, e.ToString());
}
else
{
Trace.TraceWarning(
"An error occurred while processing a new message and" +
"will be abandoned:\r\n{0}",
e);
message.SafeAbandon();
}
return;
}
Trace.TraceInformation("The message has been processed and will be completed.");
message.SafeComplete();
}
This example uses an extension method to invoke the Complete and Abandon methods of the
BrokeredMessage reliably using the Transient Fault Handling Application Block.
 J 
Why have separate CommandBus and EventBus classes?
Although at this early stage in the development of the conference
management system the implementations of the CommandBus and
EventBus classes are very similar and you may wonder why we have
both, the team anticipates that they will diverge in the future.
How scalable is this approach?
With this approach, you can run multiple instances of the Subscription-
Receiver class and the various handlers in different Windows Azure
worker role instances, which enables you to scale out your solution. You
can also have multiple instances of the CommandBus, EventBus, and
TopicSender classes in different Windows Azure worker role instances.
For information about scaling the Windows Azure Service Bus
infrastructure, see Best Practices for Performance Improvements Using
Service Bus Brokered Messaging on MSDN.
How robust is this approach?
This approach uses the brokered messaging option of the Windows
Azure Service Bus to provide asynchronous messaging. The Service
Bus reliably stores messages until consumers connect and retrieve
their messages.
Also, the peek/lock approach to retrieving messages from a
queue or topic subscription adds reliability in the scenario in which a
message consumer fails while it is processing the message. If a con-
sumer fails before it calls the Complete method, the message is still
available for processing when the consumer restarts.
What is the granularity of a topic and a subscription?
The current implementation uses a single topic (conference/commands)
for all commands within the system, and a single topic (conference/
events) for all events within the system. There is a single subscription
for each topic, and each subscription receives all of the messages pub-
lished to the topic. It is the responsibility of the CommandProcessor
and EventProcessor classes to deliver the messages to the correct
handlers.
In the future, the team will examine the options of using multiple
topics—for example, using a separate command topic for each
bounded context; and multiple subscriptions—such as one per event
type. These alternatives may simplify the code and facilitate scaling
of the application across multiple worker roles.
There may be differences in
how we invoke handlers and
what context we capture
for them: commands may
want to capture additional
runtime state, whereas
events typically don’t
need to. Because of these
potential future differences,
I didn’t want to unify the
implementations. Ive been
there before and ended up
splitting them when further
requirements came in.
There are no costs
associated with
having multiple topics,
subscriptions, or queues.
Windows Azure Service
Bus usage is billed based
on the number of messages
sent and the amount of
data transferred out of a
Windows Azure sub-region.

O  R B C
How are commands and events serialized?
The Contoso Conference Management System uses the Json.NET se-
rializer. For details on how the application uses this serializer, see
Technologies Used in the Reference Implementation” in the Refer-
ence Guide.
Impact on testing
Because this was the first bounded context the team tackled, one of
the key concerns was how to approach testing given that the team
wanted to adopt a test-driven development approach. The following
conversation between two developers about how to do TDD when
they are implementing the CQRS pattern without event sourcing
summarizes their thoughts:
“You should consider whether
you always need to use the
Windows Azure Service Bus for
commands. Commands are
typically used within a bounded
context and you may not need to
send them across a process
boundary (on the write side you
may not need additional tiers),
in which case you could use an
in memory queue to deliver your
commands.”
Greg Young, conversation with
the patterns & practices team
Developer 1: If we were using event sourcing, it would be easy to use a TDD approach when
we were creating our domain objects. The input to the test would be a command (that per-
haps originated in the UI), and we could then test that the domain object fires the expected
events. However if we’re not using event sourcing, we don’t have any events: the behavior of
the domain object is to persist its changes in data store through an ORM layer.
Developer 2: So why don’t we raise events anyway? Just because we’re not using event sourc-
ing doesn’t mean that our domain objects can’t raise events. We can then design our tests in
the usual way to check for the correct events firing in response to a command.
Developer 1: Isn’t that just making things more complicated than they need to be? One of
the motivations for using CQRS is to simplify things! We now have domain objects that need
to persist their state using an ORM layer and raise events that report on what they have per-
sisted just so we can run our unit tests.
Developer 2: I see what you mean.
Developer 1: Perhaps were getting stuck on how were doing the tests. Maybe instead of de-
signing our tests based on the expected behavior of the domain objects, we should think
about testing the state of the domain objects after theyve processed a command.
Developer 2: That should be easy to do; after all, the domain objects will have all of the data
we want to check stored in properties so that the ORM can persist the right information to
the store.
Developer 1: So we really just need to think about a different style of testing in this scenario.
 J 
Developer 2: There is another aspect of this we’ll need to consider: we might have a set of
tests that we can use to test our domain objects, and all of those tests might be passing. We
might also have a set of tests to verify that our ORM layer can save and retrieve objects suc-
cessfully. However, we will also have to test that our domain objects function correctly
when we run them against the ORM layer. Its possible that a domain object performs the
correct business logic, but can’t properly persist its state, perhaps because of a problem re-
lated to how the ORM handles specific data types.
For more information about the two approaches to testing discussed
here, see Martin Fowler’s article “Mocks Aren’t Stubs” and “Point/
Counterpoint” by Steve Freeman, Nat Pryce, and Joshua Kerievsky.
The tests included in the solution are written using xUnit.net.
The following code sample shows two examples of tests written us-
ing the behavioral approach discussed above.
public SeatsAvailability given_available_seats()
{
var sut = new SeatsAvailability(SeatTypeId);
sut.AddSeats(10);
return sut;
}
[TestMethod]
public void when_reserving_less_seats_than_total_then_succeeds()
{
var sut = this.given_available_seats();
sut.MakeReservation(Guid.NewGuid(), 4);
}
[TestMethod]
[ExpectedException(typeof(ArgumentOutOfRangeException))]
public void when_reserving_more_seats_than_total_then_fails()
{
var sut = this.given_available_seats();
sut.MakeReservation(Guid.NewGuid(), 11);
}
These are the tests we started with, but we
then replaced them with state-based tests.

O  R B C
These two tests work together to verify the behavior of the SeatsAvailability aggregate. In the first
test, the expected behavior is that the MakeReservation method succeeds and does not throw an
exception. In the second test, the expected behavior is for the MakeReservation method to throw
an exception because there are not enough free seats available to complete the reservation.
It is difficult to test the behavior in any other way without the aggregate raising events. For ex-
ample, if you tried to test the behavior by checking that the correct call is made to persist the ag-
gregate to the data store, the test becomes coupled to the data store implementation (which is a
smell); if you want to change the data store implementation, you will need to change the tests on the
aggregates in the domain model.
The following code sample shows an example of a test written using the state of the objects
under test. This style of test is the one used in the project.
public class given_available_seats
{
private static readonly Guid SeatTypeId = Guid.NewGuid();
private SeatsAvailability sut;
private IPersistenceProvider sutProvider;
protected given_available_seats(IPersistenceProvider sutProvider)
{
this.sutProvider = sutProvider;
this.sut = new SeatsAvailability(SeatTypeId);
this.sut.AddSeats(10);
this.sut = this.sutProvider.PersistReload(this.sut);
}
public given_available_seats()
: this(new NoPersistenceProvider())
{
}
[Fact]
public void when_reserving_less_seats_than_total_then_seats_become_unavailable()
{
this.sut.MakeReservation(Guid.NewGuid(), 4);
this.sut = this.sutProvider.PersistReload(this.sut);
Assert.Equal(6, this.sut.RemainingSeats);
}
 J 
[Fact]
public void when_reserving_more_seats_than_total_then_rejects()
{
var id = Guid.NewGuid();
sut.MakeReservation(id, 11);
Assert.Equal(1, sut.Events.Count());
Assert.Equal(id, ((ReservationRejected)sut.Events.Single()).ReservationId);
}
}
The two tests shown here test the state of the SeatsAvailability aggregate after invoking the Make-
Reservation method. The first test tests the scenario in which there are enough seats available. The
second test tests the scenario in which there are not enough seats available. This second test can
make use of the behavior of the SeatsAvailability aggregate because the aggregate does raise an
event if it rejects a reservation.
Summary
In the first stage in our journey, we explored some of the basics of implementing the CQRS pattern
and made some preparations for the next stages.
The next chapter describes how we extended and enhanced the work already completed by
adding more features and functionality to the Orders and Registrations bounded context. We will
also look at some additional testing techniques to see how they might help us on our journey.
More information
All links in this book are accessible from the books online bibliography available at:
http://msdn.microsoft.com/en-us/library/jj619274.

“I see that it is by no means useless to travel, if a man wants to see something new.”
Jules Verne, Around the World in Eighty Days
Changes to the bounded context
The previous chapter described the Orders and Registrations bounded context in some detail. This
chapter describes some changes that the team made in this bounded context during the second stage
of our CQRS journey.
The specific topics described in this chapter include:
• Improvements to the way message correlation works with the RegistrationProcessManager
class. This illustrates how aggregate instances within the bounded context can interact in a
complex manner.
• Implementing a record locator to enable a registrant to retrieve an order that she saved
during a previous session. This illustrates adding some additional logic to the write side that
enables you to locate an aggregate instance without knowing its unique ID.
• Adding a countdown timer to the UI to enable a registrant to track how much longer they
have to complete an order. This illustrates enhancements to the write side to support the
display of rich information in the UI.
• Supporting orders for multiple seat types simultaneously. For example, a registrant requests
five seats for a preconference event and eight seats for the full conference. This requires
more complex business logic on the write side.
• CQRS command validation. This illustrates how to make use of the model validation feature
in MVC to validate your CQRS commands before you send them to the domain.
The Contoso Conference Management System described in this chapter is not the final version of the
system. This guidance describes a journey, so some of the design decisions and implementation details
change in later steps in the journey. These changes are described in subsequent chapters.
W  
This chapter uses a number of terms, which we will describe next. For more detail, and possible alter-
native definitions, see Chapter 4, “A CQRS and ES Deep Dive,” in the Reference Guide.
Extending and Enhancing the Orders
and Registrations Bounded Context
Further exploration of the Orders and Registrations bounded context.
J :
 J 
Command. A command is a request for the system to perform an
action that changes the state of the system. Commands are impera-
tives; for example, MakeSeatReservation. In this bounded context,
commands originate from either the UI as a result of a user initiating
a request, or from a process manager when the process manager is
directing an aggregate to perform an action.
A single recipient processes a command. A command bus trans-
ports commands that command handlers then dispatch to aggregates.
Sending a command is an asynchronous operation with no return value.
Event. An event, such as OrderConfirmed, describes something
that has happened in the system, typically as a result of a command.
Aggregates in the domain model raise events.
Multiple subscribers can handle a specific event. Aggregates pub-
lish events to an event bus; handlers register for specific types of
events on the event bus and then deliver the events to the subscriber.
In this bounded context, the only subscriber is a process manager.
Process manager. In this bounded context, a process manager is a
class that coordinates the behavior of the aggregates in the domain.
A process manager subscribes to the events that the aggregates raise,
and then follows a simple set of rules to determine which command
or commands to send. The process manager does not contain any
business logic, only logic to determine the next command to send.
The process manager is implemented as a state machine, so when the
process manager responds to an event, it can change its internal state
in addition to sending a new command.
The process manager in this bounded context can receive com-
mands as well as subscribe to events.
Our process manager is an implementation of the Process Man-
ager pattern defined on pages 312 to 321 in the book Enterprise Inte-
gration Patterns: Designing, Building, and Deploying Messaging Solutions
by Gregor Hohpe and Bobby Woolf (Addison-Wesley Professional,
2003).
U 
This chapter discusses the implementation of two user stories in ad-
dition to describing some changes and enhancements to the Orders
and Registrations bounded context.
Implement a login using a record locator
When a registrant creates an order for seats at a conference, the
system generates a five-character order access code and sends it to
the registrant by email. The registrant can use her email address and
the order access code on the conference web site as a record locator
to retrieve the order from the system at a later date. The registrant
may wish to retrieve the order to review it, or to complete the regis-
tration process by assigning attendees to seats.
From the business
perspective it was
important for us to be as
user-friendly as possible:
we don’t want to block
or unnecessarily burden
anyone who is trying to
register for a conference.
Therefore, we have no
requirement for a user to
create an account in the
system prior to registration,
especially since users
must enter most of their
information in a standard
checkout process anyway.

E  E  O  R B C
Tell the registrant how much time remains to complete an order
When a registrant creates an order, the system reserves the seats requested by the registrant until the
order is complete or the reservations expire. To complete an order, the registrant must submit her
details, such as name and email address, and make a successful payment.
To help the registrant, the system displays a countdown timer to inform her how much time re-
mains to complete the order before the seat reservations expire.
Enable a registrant to create an order that includes multiple seat types
When a registrant creates an order, she may request different numbers of different seat types. For
example, a registrant may request five seats for the full conference and three seats for the preconfer-
ence workshop.
A
The application is designed to deploy to Windows Azure. At this stage in the journey, the application
consists of a web role that contains the ASP.NET MVC web application and a worker role that con-
tains the message handlers and domain objects. The application uses Windows Azure SQL Database
(SQL Database) instances for data storage, both on the write side and the read side. The application
uses the Windows Azure Service Bus to provide its messaging infrastructure. Figure 1 shows this
high-level architecture.
F 
Contoso Conference Management System high-level architecture
 J 
While you are exploring and testing the solution, you can run it
locally, either using the Windows Azure compute emulator or by run-
ning the MVC web application directly and running a console applica-
tion that hosts the handlers and domain objects. When you run the
application locally, you can use a local SQL Server Express database
instead of SQL Database, and use a simple messaging infrastructure
implemented in a SQL Server Express database.
For more information about the options for running the applica-
tion, see Appendix 1, “Release Notes.”
Patterns and concepts
This section describes some of the key areas of the application that
the team visited during this stage of the journey and introduces some
of the challenges met by the team when we addressed these areas.
R
The system uses access codes instead of passwords so the registrant
is not forced to set up an account with the system. Many registrants
may use the system only once, so there is no need to create a perma-
nent account with a user ID and a password.
The system needs to be able to retrieve order information quick-
ly based on the registrants email address and access code. To provide
a minimum level of security, the access codes that the system gener-
ates should not be predictable, and the order information that regis-
trants can retrieve should not contain any sensitive information.
Q   
The previous chapter focused on the write-side model and implemen-
tation; in this chapter we’ll explore the read-side implementation in
more detail. In particular, we’ll explain how we implemented the read
model and the querying mechanism from the MVC controllers.
In this initial exploration of the CQRS pattern, the team decided
to use SQL views in the database as the underlying source of the data
queried by the MVC controllers on the read side. To minimize the
work that the queries on the read side must perform, these SQL views
provide a denormalized version of the data. These views currently
exist in the same database as the normalized tables that the write
model uses.
The team will split the database into two and explore options for
pushing changes from the normalized write side to the denormalized
read side in a later stage of the journey. For an example of using
Windows Azure blob storage instead of SQL tables for storing the read-
side data, see the SeatAssignmentsViewModelGenerator class.

E  E  O  R B C
Storing denormalized views in a database
One common option for storing the read-side data is to use a set of
relational database tables to hold the denormalized views. You should
optimize the read side for fast reads, so there is typically no benefit
in storing normalized data because this will require complex queries
to construct the data for the client. This implies that goals for the
read side should be to keep the queries as simple as possible, and to
structure the tables in the database in such a way that they can be
read quickly and efficiently.
An important area for consideration is the interface whereby a
client such as an MVC controller action submits a query to the read-
side model.
F 
The read side storing data in a relational database
In Figure 2, a client, such as an MVC controller action, invokes a
method on the ViewRepository class to request the data it needs. The
ViewRepository class in turn runs a query against the denormalized
data in the database.
The team at Contoso evaluated two approaches to implementing
the ViewRepository class: using the IQueryable interface and using
non-generic data access objects (DAOs).
Using the IQueryable interface
One approach to consider for the ViewRepository class is to have it
return an IQueryable instance that enables the client to use language-
integrated query (LINQ) to specify its query. It is very easy to return
an IQueryable instance from many ORMs such as Entity Framework
or NHibernate. The following code snippet illustrates how the client
can submit such queries.
A normalized database
schema can fail to
provide adequate
response times because
of the excessive table
JOIN operations. Despite
advances in relational
database technology, a
JOIN operation is still
very expensive compared
to a single-table read.
The Repository pattern mediates between the domain and data mapping layers using
a collection-like interface for accessing domain objects. For more info see Martin
Fowler, Catalog of Patterns of Enterprise Application Architecture, Repository.
Application scalability and
a responsive UI are often
explicit goals when people
choose to implement the
CQRS pattern. Optimizing
the read side to provide fast
responses to queries while
keeping resource utilization
low will help you to achieve
these goals.
 J 
var ordersummary = repository
.Query<OrderSummary>()
.Where(LINQ query to retrieve order summary);
var orderdetails = repository
.Query<OrderDetails>()
.Where(LINQ query to retrieve order details);
This approach has a number of advantages:
Simplicity
• This approach uses a thin abstraction layer over the underlying
database. Many ORMs support this approach and it minimizes
the amount of code that you must write.
• You only need to define a single repository and a single Query
method.
• You don’t need a separate query object. On the read side, the
queries should be simple because you have already denormal-
ized the data from the write side to support the read-side
clients.
• You can make use of Language-Integrated Query (LINQ) to
provide support for features such as filtering, paging, and
sorting on the client.
Testability
• You can use LINQ to Objects for mocking.
There are possible objections to this approach including that:
• It is not easy to replace the data store with a non-relational
database that does not expose an IQueryable object. However,
you can choose to implement the read model differently in each
bounded context using an approach that is appropriate to that
bounded context.
• The client might abuse the IQueryable interface by performing
operations that can be done more efficiently as a part of the
denormalization process. You should ensure that the denormal-
ized data fully meets the requirements of the clients.
• Using the IQueryable interface hides the queries away. How-
ever, since you denormalize the data from the write side, the
queries against the relational database tables are unlikely to be
complex.
• Its hard to know if your integration tests cover all the different
uses of the Query method.
In the RI, using Entity
Framework, we didn’t need
to write any code at all to
expose the IQueryable
instance. We also had just
a single ViewRepository
class.

E  E  O  R B C
Using non-generic DAOs
An alternative approach is to have the ViewRepository expose custom Find and Get methods, as
shown in the following code snippets.
var ordersummary = dao.FindAllSummarizedOrders(userId);
var orderdetails = dao.GetOrderDetails(orderId);
You could also choose to use different DAO classes. This would make it easier to access different data
sources.
var ordersummary = OrderSummaryDAO.FindAll(userId);
var orderdetails = OrderDetailsDAO.Get(orderId);
This approach has a number of advantages:
Simplicity
• Dependencies are clearer for the client. For example, the client references an explicit IOrder-
SummaryDAO instance rather than a generic IViewRepository instance.
• For the majority of queries, there are only one or two predefined ways to access the object.
Different queries typically return different projections.
Flexibility
• The Get and Find methods hide details such as the partitioning of the data store and the data
access methods such as an object relational mapping (ORM) or executing SQL code explicitly.
This makes it easier to change these choices in the future.
• The Get and Find methods could use an ORM, LINQ, and the IQueryable interface behind the
scenes to get the data from the data store. This is a choice that you could make on a method-
by-method basis.
Performance
• You can easily optimize the queries that the Find and Get methods run.
• The data access layer executes all queries. There is no risk that the client MVC controller action
tries to run complex and inefficient LINQ queries against the data source.
Testability
• It is easier to specify unit tests for the Find and Get methods than to create suitable unit tests
for the range of possible LINQ queries that a client could specify.
Maintainability
• All of the queries are defined in the same location, the DAO classes, making it easier to modify
the system consistently.
 J 
Possible objections to this approach include:
• Using the IQueryable interface makes it much easier to use
grids that support features such as paging, filtering, and sorting
in the UI. However, if the developers are aware of this downside
and are committed to delivering a task-based UI, then this
should not be an issue.
The team decided to adopt the second approach because of the clar-
ity it brings to the code; in this context, we did not see any significant
advantage in the simplicity of the first approach. For examples, see
the ConferenceDao and OrderDao classes in the Registration proj-
ect.
M   
      
The UI displays data about orders that it obtains by querying the
model on the read side. Part of the data that the UI displays to the
registrant is information about partially fulfilled orders: for each seat
type in the order, the number of seats requested and the number of
seats that are available. This is temporary data that the system only
uses while the registrant is creating the order using the UI; the busi-
ness only needs to store information about seats that were actually
purchased, not the difference between what the registrant requested
and what the registrant purchased.
The consequence of this is that the information about how many
seats the registrant requested only needs to exist in the model on the
read side.
A further consequence is that the underlying storage on the read
side cannot be simple SQL views because it includes data that is not
stored in the underlying table storage on the write side. Therefore,
you must pass this information to the read side using events.
Figure 3 shows all the commands and events that the Order and
SeatsAvailability aggregates use and how the Order aggregate
pushes changes to the read side by raising events.
You can’t store this information in an HTTP session
because the registrant may leave the site between
requesting the seats and completing the order.

E  E  O  R B C
F 
The new architecture of the reservation process
The OrderViewModelGenerator class handles the OrderPlaced,
OrderUpdated, OrderPartiallyReserved, OrderRegistrantAssigned,
and OrderReservationCompleted events and uses DraftOrder and
DraftOrderItem instances to persist changes to the view tables.
CQRS 
When you implement the write model, you should try to ensure that
commands very rarely fail. This gives the best user experience, and
makes it much easier to implement the asynchronous behavior in your
application.
One approach, adopted by the team, is to use the model valida-
tion features in ASP.NET MVC.
If you look ahead to
Chapter5, “Preparing for
the V1 Release,” you’ll see
that the team extended the
use of events and migrated
the Orders and Registrations
bounded context to use
event sourcing.
 J 
You should be careful to distinguish between errors and business
failures. Examples of errors include:
• A message is not delivered due to a failure in the messaging
infrastructure.
• Data is not persisted due to a connectivity problem with the
database.
In many cases, especially in the cloud, you can handle these errors by
retrying the operation.
A business failure should have a predetermined business response.
For example:
• If the system cannot reserve a seat because there are no seats
left, then it should add the request to a wait list.
• If a credit card payment fails, the user should be given the
chance to either try a different card, or set up payment by
invoice.
T      
The countdown timer that displays how much time remains to com-
plete the order to the registrant is part of the business data in the
system, and not just a part of the infrastructure. When a registrant
creates an order and reserves seats, the countdown begins. The count-
down continues, even if the registrant leaves the conference website.
The UI must be able to display the correct countdown value if the
registrant returns to the site; therefore, the reservation expiry time is
a part of the data that is available from the read model.
Implementation details
This section describes some of the significant features of the imple-
mentation of the Orders and Registrations bounded context. You may
find it useful to have a copy of the code so you can follow along. You
can download a copy from the Download center, or check the evolu-
tion of the code in the repository on GitHub: https://github.com/
mspnp/cqrs-journey-code.
Note: Do not expect the code samples to match exactly the code
in the reference implementation. This chapter describes a step in
the CQRS journey, but the implementation may well change as we
learn more and refactor the code.
The Transient Fault Handling
Application Block from
Microsoft patterns &
practices is designed to
make it easier to implement
consistent retry behavior
for any transient faults. It
comes with a set of built-in
detection strategies for
Windows Azure SQL
Database, Windows Azure
storage, Windows Azure
Caching, and Windows
Azure Service Bus, and it also
allows you to define your
own strategies. Similarly, it
comes with a set of handy
built-in retry policies and
supports custom ones. For
more information, see The
Transient Fault Handling
Application Block.
Your domain experts
should help you to identify
possible business failures
and determine the way that
you handle them: either
using an automated process
or manually.

E  E  O  R B C
T  
A registrant may need to retrieve an order, either to view it, or to complete the assignment of at-
tendees to seats. This may happen in a different web session, so the registrant must supply some in-
formation to locate the previously saved order.
The following code sample shows how the Order class generates a new five-character order ac-
cess code that is persisted as part of the Order instance.
public string AccessCode { get; set; }
protected Order()
{
...
this.AccessCode = HandleGenerator.Generate(5);
}
To retrieve an Order instance, a registrant must provide her email address and the order access code.
The system will use these two items to locate the correct order. This logic is part of the read side.
The following code sample from the OrderController class in the web application shows how
the MVC controller submits the query to the read side using the LocateOrder method to discover
the unique OrderId value. This Find action passes the OrderId value to a Display action that displays
the order information to the registrant.
[HttpPost]
public ActionResult Find(string email, string accessCode)
{
var orderId = orderDao.LocateOrder(email, accessCode);
if (!orderId.HasValue)
{
return RedirectToAction(
"Find",
new { conferenceCode = this.ConferenceCode });
}
return RedirectToAction(
"Display",
new
{
conferenceCode = this.ConferenceCode,
orderId = orderId.Value
});
}
 J 
T  
When a registrant creates an order and makes a seat reservation, those seats are reserved for a fixed
period of time. The RegistrationProcessManager instance, which forwards the reservation from
the SeatsAvailability aggregate, passes the time that the reservation expires to the Order aggre-
gate. The following code sample shows how the Order aggregate receives and stores the reserva-
tion expiry time.
public DateTime? ReservationExpirationDate { get; private set; }
public void MarkAsReserved(DateTime expirationDate, IEnumerable<SeatQuantity> seats)
{
...
this.ReservationExpirationDate = expirationDate;
this.Items.Clear();
this.Items.AddRange(
seats.Select(
seat => new OrderItem(seat.SeatType, seat.Quantity)));
}
When the RegistrationProcessManager sends the MarkSeatsAs-
Reserved command to the Order aggregate with the expiry time that
the UI will display, it also sends a command to itself to initiate the
process of releasing the reserved seats. This ExpireRegistration-
Process command is held for the expiry duration plus a buffer of five
minutes. This buffer ensures that time differences between the serv-
ers don’t cause the RegistrationProcessManager class to release the
reserved seats before the timer in the UI counts down to zero. In the
following code sample from the RegistrationProcessManager class,
the UI uses the Expiration property in the MarkSeatsAsReserved
command to display the countdown timer, and the Delay property in
the ExpireRegistrationProcess command determines when the re-
served seats are released.
The ReservationExpiration-
Date is initially set in the
Order constructor to a
time 15 minutes after the
Order is instantiated. The
RegistrationProcess-
Manager class may revise
this time based on when
the reservations are actually
made. It is this time that
the process manager sends
to the Order aggregate in
the MarkSeatsAsReserved
command.

E  E  O  R B C
public void Handle(SeatsReserved message)
{
if (this.State == ProcessState.AwaitingReservationConrmation)
{
var expirationTime = this.ReservationAutoExpiration.Value;
this.State = ProcessState.ReservationConrmationReceived;
if (this.ExpirationCommandId == Guid.Empty)
{
var bufferTime = TimeSpan.FromMinutes(5);
var expirationCommand =
new ExpireRegistrationProcess { ProcessId = this.Id };
this.ExpirationCommandId = expirationCommand.Id;
this.AddCommand(new Envelope<ICommand>(expirationCommand)
{
Delay = expirationTime.Subtract(DateTime.UtcNow).Add(bufferTime),
});
}
this.AddCommand(new MarkSeatsAsReserved
{
OrderId = this.OrderId,
Seats = message.ReservationDetails.ToList(),
Expiration = expirationTime,
});
}
...
}
The MVC RegistrationController class retrieves the order information on the read side. The
DraftOrder class includes the reservation expiry time that the controller passes to the view using the
ViewBag class, as shown in the following code sample.
 J 
[HttpGet]
public ActionResult SpecifyRegistrantDetails(string conferenceCode, Guid orderId)
{
var repo = this.repositoryFactory();
using (repo as IDisposable)
{
var draftOrder = repo.Find<DraftOrder>(orderId);
var conference = repo.Query<Conference>()
.Where(c => c.Code == conferenceCode)
.FirstOrDefault();
this.ViewBag.ConferenceName = conference.Name;
this.ViewBag.ConferenceCode = conference.Code;
this.ViewBag.ExpirationDateUTCMilliseconds =
draftOrder.BookingExpirationDate.HasValue
? ((draftOrder.BookingExpirationDate.Value.Ticks - EpochTicks) / 10000L)
: 0L;
this.ViewBag.OrderId = orderId;
return View(new AssignRegistrantDetails { OrderId = orderId });
}
}
The MVC view then uses JavaScript to display an animated count-
down timer.
U ASP.NET MVC   
You should try to ensure that any commands that the MVC control-
lers in your application send to the write model will succeed. You can
use the features in MVC to validate the commands on both the client
side and server side before sending them to the write model.
The following code sample shows the AssignRegistrantDetails
command class that uses DataAnnotations to specify the validation
requirements; in this example, the requirement is that the FirstName,
LastName, and Email fields are not empty.
Client-side validation is primarily a convenience to the user
in that it avoids the need for round trips to the server to
help the user complete a form correctly. You still need to
implement server-side validation to ensure that the data is
validated before it is forwarded to the write model.

E  E  O  R B C
using System;
using System.ComponentModel.DataAnnotations;
using Common;
public class AssignRegistrantDetails : ICommand
{
public AssignRegistrantDetails()
{
this.Id = Guid.NewGuid();
}
public Guid Id { get; private set; }
public Guid OrderId { get; set; }
[Required(AllowEmptyStrings = false)]
public string FirstName { get; set; }
[Required(AllowEmptyStrings = false)]
public string LastName { get; set; }
[Required(AllowEmptyStrings = false)]
public string Email { get; set; }
}
The MVC view uses this command class as its model class. The following code sample from the
SpecifyRegistrantDetails.cshtml file shows how the model is populated.
@model Registration.Commands.AssignRegistrantDetails
...
<div class="editor-label">@Html.LabelFor(model => model.FirstName)</div>
<div class="editor-eld">@Html.EditorFor(model => model.FirstName)</div>
<div class="editor-label">@Html.LabelFor(model => model.LastName)</div>
<div class="editor-eld">@Html.EditorFor(model => model.LastName)</div>
<div class="editor-label">@Html.LabelFor(model => model.Email)</div>
<div class="editor-eld">@Html.EditorFor(model => model.Email)</div>
 J 
The Web.cong file configures the client-side validation based on the DataAnnotations attributes,
as shown in the following snippet.
<appSettings>
...
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
The server-side validation occurs in the controller before it sends the command. The following code
sample from the RegistrationController class shows how the controller uses the IsValid property to
validate the command. Remember that this example uses an instance of the command as the model.
[HttpPost]
public ActionResult SpecifyRegistrantDetails(
string conferenceCode,
Guid orderId,
AssignRegistrantDetails command)
{
if (!ModelState.IsValid)
{
return SpecifyRegistrantDetails(conferenceCode, orderId);
}
this.commandBus.Send(command);
return RedirectToAction(
"SpecifyPaymentDetails",
new { conferenceCode = conferenceCode, orderId = orderId });
}
For an additional example, see the RegisterToConference command and the StartRegistration action
in the RegistrationController class.
For more information, see Models and Validation in ASP.NET MVC on MSDN.

E  E  O  R B C
P     
Some information about orders only needs to exist on the read side. In particular, the information
about partially fulfilled orders is only used in the UI and is not part of the business information per-
sisted by the domain model on the write side.
This means that the system can’t use SQL views as the underlying storage mechanism on the read
side because views cannot contain data that does not exist in the tables that they are based on.
The system stores the denormalized order data in a SQL Database instance in two tables: the
OrdersView and OrderItemsView tables. The OrderItemsView table includes the RequestedSeats
column that contains data that only exists on the read side.
Column Description
OrderId A unique identifier for the Order
ReservationExpirationDate The time when the seat reservations expire
StateValue The state of the Order: Created, PartiallyReserved, ReservationCompleted, Rejected,
Confirmed
RegistrantEmail The email address of the Registrant
AccessCode The Access Code that the Registrant can use to access the Order
OrdersView Table descriptions
Column Description
OrderItemId A unique identifier for the Order Item
SeatType The type of seat requested
RequestedSeats The number of seats requested
ReservedSeats The number of seats reserved
OrderID The OrderId in the parent OrdersView table
OrderItemsView Table descriptions
To populate these tables in the read model, the read side handles events raised by the write side and
uses them to write to these tables. See Figure 3 above for more details.
The OrderViewModelGenerator class handles these events and updates the read-side repository.
 J 
public class OrderViewModelGenerator :
IEventHandler<OrderPlaced>, IEventHandler<OrderUpdated>,
IEventHandler<OrderPartiallyReserved>, IEventHandler<OrderReservationCompleted>,
IEventHandler<OrderRegistrantAssigned>
{
private readonly Func<ConferenceRegistrationDbContext> contextFactory;
public OrderViewModelGenerator(
Func<ConferenceRegistrationDbContext> contextFactory)
{
this.contextFactory = contextFactory;
}
public void Handle(OrderPlaced @event)
{
using (var context = this.contextFactory.Invoke())
{
var dto = new DraftOrder(@event.SourceId, DraftOrder.States.Created)
{
AccessCode = @event.AccessCode,
};
dto.Lines.AddRange(
@event.Seats.Select(
seat => new DraftOrderItem(seat.SeatType, seat.Quantity)));
context.Save(dto);
}
}
public void Handle(OrderRegistrantAssigned @event)
{
...
}
public void Handle(OrderUpdated @event)
{
...
}
public void Handle(OrderPartiallyReserved @event)
{
...
}

E  E  O  R B C
public void Handle(OrderReservationCompleted @event)
{
...
}
...
}
The following code sample shows the ConferenceRegistrationDbContext class.
public class ConferenceRegistrationDbContext : DbContext
{
...
public T Find<T>(Guid id) where T : class
{
return this.Set<T>().Find(id);
}
public IQueryable<T> Query<T>() where T : class
{
return this.Set<T>();
}
public void Save<T>(T entity) where T : class
{
var entry = this.Entry(entity);
if (entry.State == System.Data.EntityState.Detached)
this.Set<T>().Add(entity);
this.SaveChanges();
}
}
Notice that this ConferenceRegistrationDbContext in the read side
includes a Save method to persist the changes sent from the write
side and handled by the OrderViewModelGenerator handler class.
 J 
Q   
The following code sample shows a nongeneric DAO class that the MVC controllers use to query for
conference information on the read side. It wraps the ConferenceRegistrationDbContext class
shown previously.
public class ConferenceDao : IConferenceDao
{
private readonly Func<ConferenceRegistrationDbContext> contextFactory;
public ConferenceDao(Func<ConferenceRegistrationDbContext> contextFactory)
{
this.contextFactory = contextFactory;
}
public ConferenceDetails GetConferenceDetails(string conferenceCode)
{
using (var context = this.contextFactory.Invoke())
{
return context
.Query<Conference>()
.Where(dto => dto.Code == conferenceCode)
.Select(x =>
new ConferenceDetails
{
Id = x.Id,
Code = x.Code,
Name = x.Name,
Description = x.Description,
StartDate = x.StartDate
})
.FirstOrDefault();
}
}
public ConferenceAlias GetConferenceAlias(string conferenceCode)
{
...
}
public IList<SeatType> GetPublishedSeatTypes(Guid conferenceId)
{
...
}
}

E  E  O  R B C
R SA 
In the first stage of our CQRS journey, the domain included a
ConferenceSeatsAvailabilty aggregate root class that modeled the
number of seats remaining for a conference. In this stage of the jour-
ney, the team replaced the ConferenceSeatsAvailabilty aggregate
with a SeatsAvailability aggregate to reflect the fact that there may
be multiple seat types available at a particular conference; for exam-
ple, full conference seats, pre-conference workshop seats, and cock-
tail party seats. Figure 4 shows the new SeatsAvailability aggregate
and its constituent classes.
Notice how this ConferenceDao class contains only methods that return
data. It is used by the MVC controllers to retrieve data to display in the UI.
F 
The SeatsAvailability aggregate and its associated commands and events
This aggregate now models the following facts:
• There may be multiple seat types at a conference.
• There may be different numbers of seats available for each seat type.
 J 
The domain now includes a SeatQuantity value type that you can use to represent a quantity of
a particular seat type.
Previously, the aggregate raised either a ReservationAccepted or a ReservationRejected event,
depending on whether there were sufficient seats. Now the aggregate raises a SeatsReserved event
that reports how many seats of a particular type it could reserve. This means that the number of seats
reserved may not match the number of seats requested; this information is passed back to the UI for
the registrant to make a decision on how to proceed with the registration.
The AddSeats method
You may have noticed in Figure 3 that the SeatsAvailability aggregate includes an AddSeats method
with no corresponding command. The AddSeats method adjusts the total number of available seats
of a given type. The business customer is responsible for making any such adjustments, and does this
in the Conference Management bounded context. The Conference Management bounded context
raises an event whenever the total number of available seats changes. The SeatsAvailability class then
handles the event when its handler invokes the AddSeats method.
Impact on testing
This section discusses some of the testing issues addressed during this stage of the journey.
A     
In Chapter 3, “Orders and Registrations Bounded Context,” you saw some of the UI mockups that the
developers and the domain expert worked on together to refine some of the functional requirements
for the system. One of the planned uses for these UI mockups was to form the basis of a set of ac-
ceptance tests for the system.
The team had the following goals for their acceptance testing approach:
• The acceptance tests should be expressed clearly and unambiguously in a format that the
domain expert could understand.
• It should be possible to execute the acceptance tests automatically.
To achieve these goals, the domain expert paired with a member of the test team and used SpecFlow
to specify the core acceptance tests.
Defining acceptance tests using SpecFlow features
The first step in defining acceptance tests using SpecFlow is to define the acceptance tests using the
SpecFlow notation. These tests are saved as feature files in a Visual Studio project. The following code
sample from the ConferenceConfiguration.featurele in the Features\UserInterface\Views\Man-
agement folder shows an acceptance test for the Conference Management bounded context. A
typical SpecFlow test scenario consists of a collection of Given, When, and Then statements. Some
of these statements include the data that the test uses.
In fact, SpecFlow feature files use the Gherkin language—a domain
specific language (DSL) created especially for behavior descriptions.

E  E  O  R B C
Feature: Conference conguration scenarios for creating and editing Conference settings
In order to create or update a Conference conguration
As a Business Customer
I want to be able to create or update a Conference and set its properties
Background:
Given the Business Customer selected the Create Conference option
Scenario: An existing unpublished Conference is selected and published
Given this conference information
| Owner | Email | Name | Description | Slug | Start | End
|
| William Flash | william@fabrikam.com | CQRS2012P | CQRS summit 2012 conference (Published)| random | 05/02/2012 | 05/12/2012
|
And the Business Customer proceeds to create the Conference
When the Business Customer proceeds to publish the Conference
Then the state of the Conference changes to Published
Scenario: An existing Conference is edited and updated
Given an existing published conference with this information
| Owner | Email | Name | Description | Slug | Start | End
|
| William Flash | william@fabrikam.com | CQRS2012U | CQRS summit 2012 conference (Original) | random | 05/02/2012 | 05/12/2012
|
And the Business Customer proceeds to edit the existing settings with this information
| Description |
| CQRS summit 2012 conference (Updated)|
When the Business Customer proceeds to save the changes
Then this information appears in the Conference settings
| Description |
| CQRS summit 2012 conference (Updated)|
...
 J 
For additional examples, see the Conference.AcceptanceTests
Visual Studio solution file included with the downloadable source.
Making the tests executable
An acceptance test in a feature file is not directly executable; you
must provide some plumbing code to bridge the gap between the
SpecFlow feature file and your application.
For examples of implementations, see the classes in the Steps
folder in the Conference.Specflow project in the Conference.Ac-
ceptanceTests solution.
These step implementations use two different approaches.
The first approach runs the test by simulating a user of the sys-
tem. It does this by driving a web browser directly using the WatiN
open source library. The advantages of this approach are that it exer-
cises the system in exactly the same way that a real user would inter-
act with the system and that it is simple to implement initially. How-
ever, these tests are fragile and will require a considerable maintenance
effort to keep them up to date as the UI and system change. The
following code sample shows an example of this approach, defining
some of the Given, When, and Then steps from the feature file
shown previously. SpecFlow uses the Given, When, and Then attri-
butes to l