Are there any best practices around how specific to make events that are generated administratively, say to clean up after one-off operational issues?

For example: Say you have a credit card processing application. Payments are authorized (which deducts from the available balance) then posted (which deducts from the current balance). You had a bug that caused a few payments to have multiple authorization events, so the available balance is now lower than it should be.

You've fixed the bug and now you want to increase the available balance to recover from it. If you follow the ES pattern of keeping history immutable, that means you want compensating events. But what should those events look like? It seems like there are a few choices:

  • A generic "available balance credited by administrator" event that includes a (possibly human-readable) reason. This can be used for future one-off cleanup if needed, but the event type doesn't carry any business meaning.
  • A very specific "canceling bogus double-authorization" event. This will be used on exactly one occasion because the bug has been fixed already. The event type has business meaning here but it becomes permanent unused legacy code.
  • The standard "authorization cancelled" event that would normally be issued when a payment doesn't post. This is more meaningful than the generic event and doesn't become dead weight in the code base, but is arguably misleading since the cancellation wasn't normal.

Which of these is the preferred approach? Or is there a fourth option?


It is always recommended to strictly follow a double-entry mechanism for all financial transactions. It will save you a ton of headache when the time comes around for Accounting reconciliations and auditing.

So an overwhelming NO to changing amounts ad-hoc, especially balances of accounts that are used for dispensing or Sundry purposes.

I would go for the 3rd option with slight modifications:

  • Have a generic AuthorizationCancelled that is triggered throughout the application
  • Have a reason attribute as part of the event, with which you can identify the source
  • While handling the event, pass exactly the same financial transactions with the amount in reverse sign (the original transaction reference number should be persisted along with the reversal transaction)

There could be additional complexities to handle if you reversing transactions for payments beyond a certain time ago (because of reporting, closed books, etc.) Hopefully, you don't have those in your system.

If you have such an event already, you should reuse it, along with a custom message. If you don't have such an event, I think it is practical to introduce it as a solution to support compensating transactions generically.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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