Anyone know of a message bus implementation which offers granular control over consistency guarantees? Full ACID is too slow and no ACID is too wrong.

We're currently using Rhino ESB wrapping MSMQ for our messaging. When using durable, transactional messaging with distributed transactions, MSMQ can block the commit for considerable time while it waits on I/O completion.

Our messages fall into two general categories: business logic and denormalisation. The latter account for a significant percentage of message bus traffic.

Business logic messages require the guarantees of full ACID and MSMQ has proven quite adequate for this.

Denormalisation messages:

1. MUST be durable.
2. MUST NOT be processed until after the originating transaction completes.
3. MAY be processed multiple times.
4. MAY be processed even if the originating transaction rolls back, as long as 2) is adhered to.

(In some specific cases the durability requirements could probably be relaxed, but identifying and handling those cases as exceptions to the rule adds complexity.)

All denormalisation messages are handled in-process so there is no need for IPC.

If the process is restarted, all transactions may be assumed to have completed (committed or rolled back) and all denormalisation messages not yet processed must be recovered. It is acceptable to replay denormalisation messages which were already processed.

As far as I can tell, messaging systems which deal with transactions tend to offer a choice between full ACID or nothing, and ACID carries a performance penalty. We're seeing calls to TransactionScope#Commit() taking as long as a few hundred milliseconds in some cases depending on the number of messages sent.

Using a non-transactional message queue causes messages to be processed before their originating transaction completes, resulting in consistency problems.

Another part of our system which has similar consistency requirements but lower complexity is already using a custom implementation of something akin to a transaction log, and generalising that for this use case is certainly an option, but I'd rather not implement a low-latency, concurrent, durable, transactional messaging system myself if I don't have to :P

In case anyone's wondering, the reason for requiring durability of denormalisation messages is that detecting desyncs and fixing desyncs can be extremely difficult and extremely expensive respectively. People *do* notice when something's slightly wrong and a page refresh doesn't fix it, so ignoring desyncs isn't an option.