I also had a look at How do I deal with side effects in Event Sourcing? but the solution wasn't clear to me.

If I store "EmailSent" event in the event stream, I might issue the external request to send the email again, thinking the previous send timed out, moments before the confirmation of the first email being successfully sent arrives.

However, if I never store that, and instead have all sent email IDs persistently stored by the email service, I will never know to stop bothering the email service with my old requests to send a particular email, despite it answering "this email has been previously sent successfully" every time.

Should I do both? This way the system will stop bothering the email service a lot of the time, but when it accidentally bothers it multiple times, only one email will be sent. (Yes, the email service can never be transactional, and I still have to choose "at most once" or "at least once" but having its limited scope and data locality it can give practical results much closer to "once".)

1 Answer 1


It's pretty common to keep track of both Attempts and Acknowledgments at the client.

Acknowledgments, of course, because you don't want to pollute the network with requests that have already been served.

Attempts, because you can reduce congestion by spacing out requests, backing off if the network seems to be the problem, and so on.

The use case to work through is: what behavior do you want when the system flushes its transient memory and restarts? That tells you what you need to write down.

  • So the Email service "imports" the event that signifies the need to send the email, and then has to deal with it, in most cases never reporting back. Which locally involves SendAttempt and SendSuccess (and SendFailure) events? Commented May 23, 2019 at 11:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.