Skip to content

Allow dispatcher to batch multiple isolated dispatches per destination #857

Description

@danielmarbach

Problem

When the Outbox processes a handler or transactional session that produces multiple outgoing messages to the same destination, the dispatcher currently sends each one as a separate, individual broker call (SendMessageAsync). This is wasteful: each call incurs a network round-trip to Azure Service Bus, and cloud latency is non-trivial (see Azure Service Bus performance improvements).

Current behaviour

DispatchIsolatedOperations (the path taken for Outbox-dispatched messages) iterates over all operations and fires one DispatchForDestination task per message, even when multiple messages share the same destination. It does not batch them.

foreach (var operation in operations)
{
    // one individual SendMessageAsync call per message
    dispatchTasks.Add(DispatchForDestination(destination, isTopic, ..., message, cancellationToken));
}

Meanwhile DispatchBatchedOperations (used for non-isolated operations already grouped per destination) already uses ServiceBusMessageBatch and SendMessagesAsync to batch messages to the same destination.

Desired behaviour

DispatchIsolatedOperations should use the same batch-send path as DispatchBatchedOperations — i.e. call DispatchBatchOrFallbackToIndividualSendsForDestination — so that multiple outgoing messages to the same destination are sent in a single broker call.

The correctness constraint is already satisfied: isolated operations must not be enlisted in the receive/committable transaction. The existing Transaction? noTransaction = null guard already ensures this. Batching is purely a performance optimization and does not affect delivery guarantees.

Context

Multiple isolated dispatches (possible when the outbox is at play with a handler or a transactional session that sends multiple messages) can be batched for efficiency reasons as explained in

// Changing the dispatch consistency to be isolated to make sure the transport doesn't
// enlist the operations in the receive transaction. The transport might still want to batch
// operations for efficiency reasons but should never enlist in the incoming transport transaction.
// Otherwise a failure to ACK the incoming message after Outbox storage has been set to Dispatched
// would result in outgoing message loss.

https://github.com/Particular/NServiceBus/blob/master/src/NServiceBus.Core/Reliability/Outbox/ForceBatchDispatchToBeIsolatedBehavior.cs#L14-L19

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions