Maintaining consistent state
This is what the Durable Object Runtime API Documentation says about transactions:
Explicit transactions are no longer necessary. Any series of write operations with no intervening await will automatically be submitted atomically, and the system will prevent concurrent events from executing while awaiting a read operation (unless you use allowConcurrency: true). Therefore, a series of reads followed by a series of writes (with no other intervening I/O) are automatically atomic and behave like a transaction.
Reading this made me happy and I was further encouraged by this wonderful post on the Cloudflare blog by Kenton Varda: Durable Objects: Easy, Fast, Correct — Choose three.
However, as I thought about it more, I became convinced that I still had a problem. The input and output gates discussed in Kenton’s post provide automatic transactional atomicity in the case of a storage operation failure. However, I personally am much more likely to make a coding mistake that causes the in-memory state of my durable object to become out of sync with storage and even for storage under two different keys to no longer be self-consistent. Take a look at the fetch handler for this simple DO and see if you can spot the flaw.