Let's assume that we want to implement a small security subsystem for a financial application that warns the users via email if a strange pattern is detected. For this example, the pattern will consist in three transactions as the ones depicted. The security subsystem can read events from the main system from a queue. What I would like to get is an alert that is a direct consequence of the events that happen in the system, without an intermediate representation that models the current state of the pattern.Monitoring activatedTransaction processedTransaction processedTransaction processedAlert triggered (id: 123)Email for alert sent (for id: 123)Transaction processedHaving this in mind, I thought event sourcing could apply here very well, although I have a question without a clear answer. The alert triggered in the example has a clear side effect, an email needs to be sent, a circumstance that should only happen once. Therefore, it shouldn't happen when replaying all the events of an aggregate. To some extent, I see the email that needs to be sent similar to the materializations generated by the query side that I have seen so many times in the CQRS/Event sourcing literature, with a not so subtle difference though.In this literature, the query side is built from event handlers that can generate a materialization of the state at a given point reading again all the events. In this case, though, that can't be accomplished exactly like that for the reasons explained before. The idea that every state is transient does not apply so well here. We need to record the fact that an alert was sent somewhere.An easy solution for me would be having a different table or structure where you keep records of the alerts that were previously triggered. As we have an ID, we would be able to check if an alert with the same ID was issued before. Having this information would make the SendAlertCommand idempotent. Several commands can be issued, but the side effect will only happen once.Even having that solution in mind, I don't know if this is a hint that there is something wrong with this architecture for this problem. Is my approach correct?Is there any place where I can find more information about this?It is strange that I haven't been able to find more information about this. Maybe I have been using the wrong wording.Thank you so much!
How do I deal with side effects in Event Sourcing?
event programming;cqrs;event sourcing
How do I deal with side effects in Event Sourcing?Short version: the domain model doesn't perform side effects.  It tracks them.  Side effects are performed using a port that connects to the boundary; when the email is sent, you send the acknowledgement back to the domain model.This means that the email is sent outside of the transaction that updates theevent stream.Precisely where, outside, is a matter of taste.So conceptually, you have a stream of events likeEmailPrepared(id:123)EmailPrepared(id:456)EmailPrepared(id:789)EmailDelivered(id:456)EmailDelivered(id:789)And from this stream you can create a fold{    deliveredMail : [ 456, 789 ],    undeliveredMail : [123]}The fold tells you which emails haven't been acknowledged, so you send them again:undeliveredMail.each ( mail -> {    send(mail);    dispatch( new EmailDelivered.from(mail) );}     Effectively, this is a two phase commit: you are modifying SMTP in the real world, and then you are updating the model.The pattern above gives you an at-least-once delivery model.  If you want at-most-once, you can turn it aroundundeliveredMail.each ( mail -> {    commit( new EmailDelivered.from(mail) );    send(mail);}     There's a transaction barrier between making EmailPrepared durable and actually sending the email.  There's also a transaction barrier between sending the email and making EmailDelivered durable.Udi Dahan's Reliable Messaging with Distributed Transactions may be a good starting point.