It is well known that MongoDB does not support transactions involving multiple documents. Atomicity in MongoDB is restricted to single document writes and, as a result, if you find yourself in a situation where you need to update multiple documents in “all or nothing” fashion, you’re stuck. For the most part, you can and should model your data in a way that avoids super close ties between documents but there are cases where you need a transaction.

Take the classic example of transferring cash between two bank accounts. To transfer $20, the steps are:

Subtract 20 from the sender’s balance

Add 20 to the receiver’s balance

As you can see, It’s possible for the first step to succeed while the second step, for whatever reason, fails. This leads to inconsistent data, leaving the sender $20 short and the receiver, expectant. This kind of operation must be done in a transactional manner i.e. if any of the steps fail, all the steps fail. This is where two phase commits come into play.

With Fawn, you can save, update, and delete documents and files across collections in a transactional manner.

If you’re new to two phase commits, the process is described well in the MongoDB docs. The main idea is:

store all the information about the steps of an operation in a transaction and store the transaction.

retrieve the transaction and perform it’s steps. after performing each step, update the state of the transaction to reflect that.

A transaction is complete when it’s in a final state

In the event of an error, the transaction can be retrieved and all the steps that completed before the error can be reverted.