domain driven design – Event sourcing with concurrency against projections

An observation: “simplified” problems are rarely a good idea in DDD, because the details of the problems tend to matter, and contrived examples rarely have the details fleshed out.

How do I properly address this issue?

For the problem as described, you would probably do something like this: at step #1, you would capture a snapshot of some pool of your customers that are going to be participants in this process, and then from that point forward you would handle each of those customers in parallel, performing the update, sending off the email, and so on. The “projection” that describes their hair color would be updated asynchronously, until eventually it was again consistent with the information in your book of record.

If the process itself were important, then you would have a stream of events for tracking it, and projections off of that stream so that you could see whether the process was complete, what works is outstanding, and so on.

But this report, like all of the others, is going to be a snapshot of information that is not necessarily synchronized with what information is “live”. For instance, you might be looking at a report that shows you our best guess at the progress as of close of business the previous day.

In any distributed system, reports are going to be stale – the human reader is probably sitting a nanosecond from the display, the report needs time to copy across the network, and so on. Part of what we need to work out, in our designs, is how much “stale” the business can tolerate, and whether or not we can mitigate the mistakes that are made when we process stale data.

This isn’t specific to event sourcing, of course. We have exactly the same sorts of problems when our book of record is a relational database. The big difference between the two cases is that relational databases have general purpose locking strategies available that allows us to coordinate writes in a way that may not be available in our event store (aka locking multiple streams to make a coordinated change).

A useful reference is Pat Helland’s paper Data on the Outside vs Data on the Inside. Another to review would be Udi Dahan’s Race Conditions Don’t Exist.