# Auto Ack (/sdks/kotlin/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` in the `receiveQueuesMessages` config block. With it enabled, delivery and acknowledgment happen as one atomic step on the broker side, so there's no separate `msg.ack()` call and no in-flight "pending" state for the message to sit in.

**Gotchas:** if your consumer crashes or throws after `receiveQueuesMessages` 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/kotlin/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, `maxItems` and `waitTimeoutMs` are your only throttles — there's no visibility-timeout window to tune.

## Prerequisites [#prerequisites]

* KubeMQ server running on `localhost:50000`
* Kotlin SDK installed (`implementation("io.kubemq.sdk:kubemq-sdk-kotlin:1.0.1")`)

## Code [#code]

```kotlin title="AutoAckExample.kt"
package io.kubemq.sdk.examples.queuesstream

import io.kubemq.sdk.client.KubeMQClient
import io.kubemq.sdk.queues.queueMessage
import kotlinx.coroutines.runBlocking

private const val ADDRESS = "localhost:50000"
private const val CLIENT_ID = "kotlin-queues-auto-ack"
private const val CHANNEL = "kotlin-queues.auto-ack"

fun main() = runBlocking {
    val client = KubeMQClient.queues {
        address = ADDRESS
        clientId = CLIENT_ID
    }

    client.use {
        try {
            client.createQueuesChannel(CHANNEL)

            // Send messages
            repeat(3) { i ->
                client.sendQueuesMessage(queueMessage {
                    channel = CHANNEL
                    body = "Auto-ack msg ${i + 1}".toByteArray()
                })
            }

            // Poll with auto-ack enabled (messages acknowledged automatically)
            println("Polling with autoAck=true...\n")
            val response = client.receiveQueuesMessages {
                channel = CHANNEL
                maxItems = 10
                waitTimeoutMs = 5000
                autoAck = true
            }

            response.messages.forEach { msg ->
                println("  Received (auto-acked): ${String(msg.body)}")
            }
            println("\n${response.messages.size} messages auto-acknowledged.")
        } finally {
            try { client.deleteQueuesChannel(CHANNEL) } catch (_: Exception) {}
        }
        println("Done.")
    }
}
```

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

* Setting `autoAck = true` in the receive config automatically acknowledges messages on delivery.
* No need to call `msg.ack()` on individual messages.
* Use auto-ack for fire-and-forget consumption where message loss on processing failure is acceptable.
* For at-least-once delivery guarantees, use `autoAck = false` with explicit acknowledgement.

## Related [#related]

* [Stream Receive](/sdks/kotlin/how-to/queues/stream-receive)
* [Ack All](/sdks/kotlin/how-to/queues/ack-all)
* [Queues Reference](/sdks/kotlin/reference/queues)
