Tree with lightning — Photo credit George Hodan at publicdomainpictures.net

Command Events — A First Class Citizen of Event-Storming

Rene Parra
HomeAway Tech Blog
Published in
6 min readSep 6, 2018

--

In previous stories, here, and here, I’ve discussed domain events and business events. As CQRS, event-sourcing, and event-storming increase in popularity, system designs increasingly are polarizing to command-oriented architectures (writes) and/or query-oriented architectures (reads).

Let’s take a look at the previous blog post case study example in more detail and focus on something that was mentioned in passing:

the command event.

A BookingRequested command event schema is provided as an example:

Command Event Sample

Looking at this more closely:

  • The bookingRequestedId is the unique ID for this command
  • The command event has a timestamp
  • There are related IDs on the event. These IDs are the primary IDs of entities related to this command (e.g. travelerId, propertyId).
  • All other information is related to the command itself (e.g., checkInDate, checkOutDate, amount, currency).

Introducing the Command Event

This simple concept is a powerful one. We define a command event as having the following characteristics:

  • Declared as a verb in the past tense
  • Immutable
  • Stateless
  • Has a timestamp

Some observations

The command is a verb declared in the past tense.

It is not called a BookingRequest, for example. It is a BookingRequested event. This is important because it achieves two things:

  • It asserts that this is an action (not a noun).
  • It punctuates that this action has occurred and is not some process that is going to happen, or is happening.

This basic act of recording something that occurred is foundational to this design mindset.

The command is immutable.

Clearly from the schema, there is nothing more to be done to this command. It is immutable and, arguably, atomic. It contains all data collected at the point of observation, forming a digital footprint to be used subsequently by operational and analytical systems.

It does not change, nor can it be changed.

The command is stateless.

Since the command is immutable, it is also stateless. Any data associated with the command is forever frozen in history as what actually happened. It is pure truth. It does not change.

The command has a timestamp

All events should record when they occurred.

All your command events are belong to you!

Reference: All your base are belong to us

Suppose you were to list all of your command events for your company or business? What if I told you that if you did, an interesting pattern would emerge? If you were able to list all the command events for your company or business, and get a team of folks to apply “gravity” to these events —cohesively group them by how “related” or “similar” they are — you would have a very interesting set of groupings indeed.

Hypothesis: By listing all related command events and grouping them by “relation” or “similarity” — Eric Evans’ Domain-Driven Design concept of aggregates or domains emerge as a natural result!

This process is otherwise known as: event-storming.

Event Storming 10,000-ft view

Lets look at the above example with some other command events.

Sampling of Command Events

One might choose to group these events as follows:

Sample grouping of Command EVents

When you look at the 4 command events that are grouped for “Booking”, a separate object that tracks the 4 states (requested, accepted, cancelled, and expired) emerges. This grouping might make sense to define as a separate entity. This Booking aggregate or domain emerges as a new domain object that has state and can change. The Booking domain represents a data gravity or data cohesion that is specific to its domain and consequently very different from other domains such as property content, customer service, or maybe even viewing existing bookings.

This aggregate, or domain, becomes foundational for querying current state and useful for other parts of the system to discover aspects of the nouns or domains that have state and can change. (It also turns out to be quite useful for combating Conway’s Law, but that is a segue topic outside the scope of this article.)

This process of eliciting command events and subsequently determining emergent domains/aggregates is the process known as event-storming, please refer to that post for the benefits and a deeper dive of event-storming.

What do I do with my command events?

Put simply, you store them.

Store your command events (verbs) into a data store

By storing command events into an event store, downstream systems can asynchronously process this immutable system of record for a variety of use cases. The yellow “bar” is a stream of command events stored in a [reliable, highly available] streaming platform.

Today, this process is called event-sourcing. Several solutions are emerging as viable solutions to store all your command events, in order, forever.

The primary use case of the command events is to process them, usually to aggregate them into some [semi-]stateful representation. These microservices are then available so that clients can perform queries in real time to determine the aggregate result of what has occurred, usually via an API call. These final resulting states can be broadcast as a stream of domain events and retained, as shown by the green bar below.

Aggregate the stream of commands into domain events that usually convey state.

Now, downstream systems can query the state of bookings and find out what state any given bookingId is in. Also simple analytics becomes possible. Based on the type of queries that may be supported, different analytic systems can be deployed to support a variety of query types (e.g., cube time series, cube slice-and-dice, relational, key-lookup, etc).

Enrich domain event streams into business events (facts) that drive the business.

With the final addition of business events, democratized but shareable analytics processing can now occur within the enterprise. These business events represent enriched streams of facts that are used to populate downstream analytical systems. These enriched streams prove useful for a variety of teams to leverage an authoritative and distributed source of truth (SOT) that works across teams and contexts. Should a team need to change the context a bit, they are encouraged to further enrich a stream of their own, or refactor a common stream upstream (duplication intentional) from which they fork their particular enriched stream. In such a manner, all teams agree upon a set of shared facts that collectively drive the business.

Putting it all together

Stream processing as the digital nervous system of the enterprise.

Here are all the streams of events in one figure.

The patterns outlined here are for educational purposes only. However the hope is that with these patterns, teams can begin to evolve their monolithic designs to designs that are more conducive to microservices and ephemeral cloud deployments that scale horizontally and elastically.

In my next blog post, I will go through this with a bit more [opinionated] detail with actual github code examples for you to try out and take it for a spin.

Acknowledgements

--

--