KubeMQ
Client SDKsC#How-to guidesQueues

Batch Send

Send multiple KubeMQ queue messages in a single batch using the C# SDK for efficient delivery.

Overview

Batch send groups several queue messages into one call instead of sending them one at a time. Reach for it when publishing many related items together — importing records, fanning out a set of jobs, replaying a backlog — since sending each message individually pays a full round trip per message, while batching amortizes that cost across the whole set.

It works by building an IEnumerable<QueueMessage>, then passing the collection to client.SendQueueMessagesAsync(messages) in a single gRPC call. The broker assigns each message its own MessageId and persists them independently, reporting any partial failure per message in the result list.

Gotchas: batching isn't atomic — the broker can accept some messages and reject others in the same call, so always check each message's result instead of trusting an overall success; a batch is still one bounded request, so it doesn't help continuous, open-ended publishing (use SendQueueMessagesUpstreamAsync, which streams instead of batching, for that); and very large batches raise the size and latency of that single call, so there's a practical ceiling before splitting into multiple batches pays off.

Prerequisites

  • KubeMQ server running on localhost:50000
  • C# SDK installed (dotnet add package KubeMQ.SDK.CSharp)

Code

Program.cs
// KubeMQ .NET SDK — Queues: Batch Send and Receive
//
// This example demonstrates sending and receiving batches of queue messages.
// Batch operations reduce network round trips for high-throughput scenarios.
// Uses QueueDownstreamReceiver.PollAsync for transactional message settlement.
//
// Prerequisites:
//   - KubeMQ server running on localhost:50000
//   - dotnet run

using KubeMQ.Sdk.Client;
using KubeMQ.Sdk.Queues;
using System.Text;

await using var client = new KubeMQClient(new KubeMQClientOptions
{
    ClientId = "csharp-queues-batch-send-client",
});
await client.ConnectAsync();

Console.WriteLine("Connected to KubeMQ server");

// Send a batch of messages
var messages = Enumerable.Range(1, 10).Select(i => new QueueMessage
{
    Channel = "csharp-queues.batch-send",
    Body = Encoding.UTF8.GetBytes($"Batch item #{i}")
}).ToList();

var batchResult = await client.SendQueueMessagesAsync(messages);
Console.WriteLine($"Sent batch of {messages.Count} messages");

// Receive via downstream receiver (supports manual settlement)
await using var receiver = await client.CreateQueueDownstreamReceiverAsync();

var batch = await receiver.PollAsync(new QueuePollRequest
{
    Channel = "csharp-queues.batch-send",
    MaxMessages = 10,
    WaitTimeoutSeconds = 10,
    AutoAck = false,
});

Console.WriteLine($"Received {batch.Messages.Count} messages:");

foreach (var msg in batch.Messages)
{
    Console.WriteLine($"  {Encoding.UTF8.GetString(msg.Body.Span)}");
    await msg.AckAsync();
}

Console.WriteLine("Done.");

How It Works

  • SendQueueMessagesAsync(IEnumerable<QueueMessage>) sends all messages in a single gRPC call, reducing round-trip overhead compared to calling SendQueueMessageAsync in a loop.
  • Each message in the batch is independent — the broker assigns a unique MessageId to each and persists them individually. A partial failure is reported per-message in the result list.
  • The downstream receiver is created once and reused for the poll; AutoAck = false with per-message AckAsync() provides at-least-once delivery semantics.
  • For very high throughput, consider SendQueueMessagesUpstreamAsync (stream-based) which avoids the batch size limits of the single-call API.

Was this page helpful?

On this page