Domain driven design with eventual consistency

domain-driven-designevent-sourcingeventual-consistency

My domain aggregate is struggling with simple business logic so I feel like I have modeled it incorrectly.

The architecture I have right now uses domain driven design with event sourcing. The domain aggregate produces events which get digested by subscribers. Eventually the event queue will be empty and the view store completely updated.

Where it struggles is with large collections of objects on the aggregate and the need to coordinate between domains.

So one aggregate is a ChatAggregate which allows people to add comments. However a user can only add one comment per hour or one comment for the entire life time. My domain object cannot keep all comments in memory but I still need my ChatAggregate to apply this business logic. Because of the eventually consistent nature of my view store, I cannot let my aggregates query it for business logic. How does DDD handle when an aggregate needs access to a lot of data?

The second issue I have is when a domain command is being processed, I want to query other aggregates before processing the command with the target aggregate. An example is before creating a new ChatCommentAggregate instance, I would like to query the ChatAggregate to see if the chat is still open.

Best Answer

If eventual consistency will not do then you'll need a way to store 100% consistent data on the transactional/write/domain side of things.

That being said, it is sometimes possible to implement a business rule slightly differently but still get the same result. For instance, you could add a list of ChatAggregateComment value objects to your ChatAggregate that store, say, the UserId, CommentId, and DateCommented. This list would grow only as big as the number of people involved in the chat. However, if even that is going to be too large then you could denormalize the data and store this same list as immediately consistent on your write side and then query table through some domain-side query interface.

As far as creating a new ChatCommentAggregate is concerned you could use your ChatAggregate as the factory for a ChatCommentAggregate. Your rule could be applied within the ChatAggregate.CreateComment method.