How to handle changing the implementation of Events when using Data.Acid

I have a moderately sized application that uses Data.Acid for persistence and I've encountered a situation where I need to update the implementation of one of my Update events for the next version of the server. I.e. I have something like

myUpdate :: Update MyState ()
myUpdate = <some outdated implementation>

Now, obviously I can't just change the implementation haphazardly as it would corrupt my transaction history, so I was wondering how people usually handle this. The way I see it my options are:

  1. Stop the server. Run createCheckpoint for my AcidState. Update the Event implementation and then restart the server. Since we load from a fresh snapshot, the changed Update should never trigger for the old events.

  2. Create a a new Update with a new name (like myUpdate_v2) and update my server logic to only use myUpdate_v2 everywhere instead of the original myUpdate.

I think both options have their merits. (1) is nicer since I don't need to retain the old functionality in my codebase but it has to be done very carefully for each server I update or I risk corrupting data. (2) is safer (especially if I remove the old myUpdate from my module's exports so I can be sure I don't accidentally use the old implementation anywhere), but it feels a bit ugly otherwise.

Is there some better way of doing this? I see this as something I will definitely encounter every then and again in a long-lived project so I would like to have a good, standard workflow for applying changes to the implementation of my events.


The solution is to not use higher order functions like 'alter'. The benefits of acid-state (ACID guarantees, running code remotely, etc) comes at the cost of only using serialisable data. This restriction is unlikely to ever be lifted.

Usually this is a not a big problem; Just specialise your code. If this doesn't cut it, maybe you want to keep your state in an MVar.