I’m puzzled by a part of DDD, and while I suspect the question isn’t about EventStore specifically, I’ll use it to demonstrate my point since - as far as I can tell, an event stream is meant to represent the state of a single aggregate.
I’ll use the classic banking analogy. Let’s say I’ve got an ‘Account’ aggregate, and you’re able to issue commands:
- ‘Deposit’ to add an amount to the Account.
- ‘Withdraw’ to subtract an amount from the Account.
The ‘Withdraw’ command will have rules saying that you cannot withdraw more than is in the Account.
The corresponding events would be:
AccountDeposited { AccountId: AccountID, Amount: number }
AccountWithdrawn { AccountId: AccountID, Amount: number }
To implement this, I’ve have an Account stream which would consist of a sequence of these events, and my aggregate can be loaded from this. For example:
AccountDeposited { AccountId: 1, Amount: 30 }
AccountDeposited { AccountId: 1, Amount: 20 }
AccountWithdrawn { AccountId: 1, Amount: 15 }
Based on the above Account events, we know that the Account has an amount of 35, so if someone tries to withdraw 40 then we can prevent this.
So far, so simple.
But a common more complex scenario is transferring between accounts, and modelling this as a single transaction. I’ve seen this modelled as a separate ‘Transfer’ aggregate, with an event such as:
TransferRequested { FromAccount: AccountID, ToAccount: AccountID, Amount: number }
But if this is a separate aggregate, and therefore a separate stream, then I won’t be able to fully load my Account aggregate any more right? For example, the following events:
AccountDeposited { AccountId: 1, Amount: 30 }
TransferRequested { FromAccount: 1, ToAccount: 2, Amount: 25 }
As far as the overall system is concerned, Account 1 now has 5, Account 2 now has 25. But the individual event streams for these aggregates don’t allow either to be loaded sufficiently to enforce my original rule of ‘don’t allow any more to be withdrawn than is in the account’.
Hopefully this makes sense.