# Auto Ack (/sdks/csharp/how-to/queues/auto-ack)



## Overview [#overview]

**Auto-ack** is the fire-and-forget receive mode for queues: the broker marks a message as consumed the instant it hands it to your client, instead of waiting for your code to settle it. Reach for it when the work is idempotent, low-value, or cheap to lose — a metrics ping, a cache warm, a best-effort notification — and you'd rather not carry the bookkeeping of explicit acknowledgment for every message.

It works by setting `AutoAck = true` on the `QueuePollRequest` passed to `PollAsync`. With it enabled, delivery and acknowledgment happen as one atomic step on the broker side, so there's no separate `AckAsync()` call and no in-flight "pending" state for the message to sit in.

**Gotchas:** if your consumer crashes or throws after `PollAsync` returns but before it finishes processing, that message is gone for good — auto-ack gives you no chance to nack or requeue it, unlike [Ack & Reject](/sdks/csharp/how-to/queues/ack-reject). It's an at-most-once model, so never use it for messages where losing one silently would matter. And because acknowledgment happens on delivery, `MaxMessages` and `WaitTimeoutSeconds` are your only throttles — there's no visibility-timeout window to tune.

## Prerequisites [#prerequisites]

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

## Code [#code]

```csharp title="Program.cs"
// KubeMQ .NET SDK — QueuesStream: Auto-Ack on Downstream Receive
//
// This example demonstrates receiving messages via the downstream receiver API
// with AutoAck enabled. Messages are automatically acknowledged upon receipt,
// so no manual ack/nack is needed.
//
// Prerequisites:
//   - KubeMQ server running on localhost:50000
//   - Send some messages to "csharp-queues.auto-ack" first
//   - dotnet run

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

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

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

await using var receiver = await client.CreateQueueDownstreamReceiverAsync();

var batch = await receiver.PollAsync(new QueuePollRequest
{
    Channel = "csharp-queues.auto-ack",
    MaxMessages = 5,
    WaitTimeoutSeconds = 5,
    AutoAck = true,
});

foreach (var msg in batch.Messages)
{
    Console.WriteLine($"Auto-acked: {msg.MessageId} — {Encoding.UTF8.GetString(msg.Body.Span)}");
}

Console.WriteLine("Done.");

```

## How It Works [#how-it-works]

* Setting `AutoAck = true` in `QueuePollRequest` instructs the broker to acknowledge all returned messages on behalf of the receiver before they are delivered. No `AckAsync()` call is needed.
* This is the simplest receive pattern and has the lowest latency, but provides no at-least-once guarantee: if the consumer crashes after receiving but before processing, the messages are gone.
* Use `AutoAck = false` (plus explicit `AckAsync` / `NackAsync`) whenever your processing is fallible and you need retry-on-failure semantics.
* `batch.Messages` is a list — iterate it and process each message synchronously or in parallel before the next `PollAsync`.

## Related [#related]

* [Pattern overview](/learn/queues/getting-started)
* [C# SDK Reference](/sdks/csharp/reference)
* [Send & Receive](/sdks/csharp/tutorials/send-receive)
* [Ack All](/sdks/csharp/how-to/queues/ack-all)
