We have investigated the case of ensuring money transfers between banks can be achieved without distributed transactions.
Consider now the example of purchasing something on-line. The blog Distributed Transactions: The Icebergs of Microservices by Graham Lea gives the example of a simple microservice system for buying a book online using the book store’s proprietary payment credits.
He points out rightly that distributed transactions should be avoided, and it's very important to consider the impact of avoiding them.
However he suggests a cumbersome solution which is hard to implement correctly and efficiently (see the talk by Udi Dahan to appreciate how subtle and difficult it is to get it right). It isn't based on double entry book-keeping and it's only eventually consistent. It involves a "commander" which is the primary handler for the event. It handles the original event with a single commit, and then takes responsibility for asynchronously communicating the secondary effects to other services. The commander uses a retry loop and therefore there's a need for idempotence.
Why are these poor approaches the norm in the software industry? Consider Graham Lea's comment:
At Tyro, where we currently do a lot of communication through RabbitMQ, we have a pattern we call “Async Rabbit”. The “Async” part is there not because because of the asynchrony introduced by using a message broker, but because we are submitting messages into the message broker asynchronously within the application, so as not to create a bad distributed transaction.
The answer appears to be because his company does "a lot of communication through RabbitMQ", and RabbitMQ embodies anti-patterns.
According to the RabbitMQ website, as of 2019, RabbitMQ have more than 35,000 production deployments world-wide at small startups and large enterprises. That's just one of the message broker products that invite poor solutions.
It seems, unfortunately, poor solutions are the norm (at least in the software industry for business services and applications).
A vastly better solution is possible. This involves managing stock just like money with the approach taken with money transfers between banks.
That means there are persistent queues which contain records which represent promises to send stock. Each participiating database has stock accounts as well as monetary accounts. The double entry book-keeping concept is applied on the stock ledger in each participating database, to ensure it balances just as for its monetary ledger.
A transaction on a participating database often involves both transfers of money and stock. For example, a single transaction may atomically make the following four updates to its local database:
Note that this one transaction is balanced in three ways: