Eventual consistency, CQRS and interaction design

Gabriel Schenker’s excellent series of posts on “How we got rid of the database” offers a great insight on the benefits of a CQRS/ES application. One of the problems often seen with designing user interfaces that introduce eventual consistency into the mix is how to present this new paradigm to the end user. But whether we’ve thought or not, eventual consistency is all around us, as Gabriel points out in a few examples:

  • Ordering a book online, dealing with stock
  • Unit price of a stock changing
  • Ordering coffee where the barista starts making the coffee before your payment is complete
  • Organizing care during an accident (a little morbid)

In all of these situations, the user is dealing with more than one agent/service boundary. There is already an expectation on the user side that there needs to be coordination involved.

In the human examples, coffee shop for example, the barista and the cashier, we have an interaction with the cashier/customer, and an interaction with the cashier/barista:

image

Transactionally, I have one transaction between the cashier and customer (place the order) and one transaction between the barista and the cashier (make the order).

Looking at eventual consistency, it’s between these two transactions/interactions that we have eventual consistency. But inside each transaction, it either succeeds or fails, and does so synchronously. I don’t hand the cashier my credit card and go run an errand to come back later. I stand at the cash register, waiting, until my payment succeeds.

If it succeeds, my order is confirmed. If it fails, the cashier issues a compensating action to the barista to say “toss that order in the bin”.

Eventual consistency in interaction design

Translating the above to a UI, making the order is behind the scenes, but paying for the order certainly is synchronous. The user expects (for this small transaction) that they pay, and the order is complete. There is no recourse during payment for “emailing the customer” or yelling out their name on the store PA to please come back and pay. It is not a fire-and-forget message or a fire-and-wait-perhaps-it-most-likely-succeeds message. It is a “pay now or your order is cancelled” message.

Users are smart. For interactions that they expect to be fire-and-forget (like the ecommerce example), we can shape our interactions to more closely mold what is actually happening, and the user will not complain. For example, in Amazon, placing an order is synchronous, but fulfilling your order is not. How do they accomplish this in the UI?

image

On the confirmation page after submitting an order (which is most definitely synchronous), it’s clear that what we are submitting is an order request. An order request to be fulfilled later. If things go wrong, we’ll have other means to fix the order through offline means, but we’ve already set the user expectation through simple statuses that “this is behind the counter stuff”.

But this is expected because the user is interacting with multiple agents. Eventual consistency is an obvious result of interactions between multiple humans and between services.

What about a single, event-sourced application?

Communicating intent

In many event-sourced applications I see, the interaction is something like:

image

This can work well if the user already expects the submission to be a “request” that may or may not fail. We might up the probability of it succeeding by pre-validating. But if no one else is using my aggregate, why might the command fail in the back end? It probably shouldn’t but now we’ve just put a wacky interaction on top of the user where it’s not needed.

Looking at a single aggregate, commands can fail when the aggregate has changed. Aggregates can change when other people are interacting with it, which can be a fairly low occurrence. If the occasions of multiple people working on the same aggregate instance is low, why do an async command at all?

Instead, you can do a synchronous execution against the aggregate and an async update to the view models.

But back to that pesky problem of users waiting to have the view model updated. If you have users that have to wait to have the view model updated to see their results, you have built the wrong user interface. Results should be immediate. Did you receive my command or not? Yes or no? What is the status of my command? This is the interaction you should have.

And if the user doesn’t think like this with their interaction and information, then you’ve picked an eventually consistent model that doesn’t apply.

Eventual consistency arises in interactions between service boundaries. It’s much more rare inside service boundaries.

If you slap on eventual consistency on places where it wasn’t before or isn’t obvious that it’s needed/necessary to users, get ready to do some parlor tricks to create the illusion of immediate consistency.

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Jimmy Bogard

I'm a technical architect with Headspring in Austin, TX. I focus on DDD, distributed systems, and any other acronym-centric design/architecture/methodology. I created AutoMapper and am a co-author of the ASP.NET MVC in Action books.
This entry was posted in CQRS, Domain-Driven Design. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Anonymous

    Great article Jimmy, but it left me with “Ur doin it rong!” and no great solution. Are you suggesting we run part of the domain in the web app and part in command handlers? If so, how would you publish events from the part running in the web app? If not, how would you suggest we make reliable, synchronous calls in to the domain? I’d rather not host web services on my SQL box. I know there’s a a lot of “it depends” in there, but I’d like to know how you connect everything.

  • Anonymous

    Thanks, Jimmy – good clarification. Unfortunately I’ve had the pleasure of learning this the hard way. 

  • http://www.facebook.com/tyronemichael Tyrone Michael Avnit

    I have been thinking about this quite a bit lately, and I am wondering why more applications dont implement the following. Take Backbone for example which has changed recently to allow optimistic updating when saving/updating the model. Now I am unsure if this is directly applicable to the article, but it seems so. When doing updates or creates to a model (non transactional), do I need to wait for a success response from the server? Or can I presume that the update/create was successful? Obviously the latter will lead to a snappier application because results are immediate. How would you handle errors with an optimistic application?

    • Anonymous

      I’ll have a follow-up on this one, it’s a whole topic in an of itself!

      • Sam Critchley

        I’m stuck on this too. If event handlers fail how to recover! Another doozy is if you change the system is the only way to deploy by replaying your entire event store – what if you have millions of events?

  • http://tracker1.info/ Tracker1

    There’s a serious issue dealing with synchronous communication, as in via XHR in the actual browser.  That is the single-threaded nature of JavaScript within the browser.  Most recently I looked at the client demos for ADL’s Project TinCan (an eLearning specification being worked on)… the default client scripts are using Synchronous XHR requests… The problem is if your page has other interactions, such as animation that is script driven while this communication is happening.  This can also include GIF animations, and other issues that are in effect locked during transmission.

    It’s less about async being more correct for a transactional state from a browser to a server, and more about the function of the browser’s nature.  Just wanted to make this point.

    • http://daniellang.net/ Daniel Lang

       Yes, I see your point, but in how far does it relate to the the event-sourcing topic of the post?

  • Pingback: The Morning Brew - Chris Alcock » The Morning Brew #1133

  • Pingback: Distributed Weekly 161 — Scott Banwart's Blog

  • Pingback: Friday links 34 « A Programmer with Microsoft tools

  • Pingback: CQRS and user experience | Jimmy Bogard's Blog

  • Pingback: Initial thoughts on some new-fangled things part 1 « The Shade Tree Developer