# Auto Ack (/sdks/java/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 `autoAckMessages(true)` on the `QueuesPollRequest` passed to `receiveQueueMessages`. 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 `receiveQueueMessages` 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/java/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, `pollMaxMessages` and `pollWaitTimeoutInSeconds` are your only throttles — there's no visibility-timeout window to tune.

## Prerequisites [#prerequisites]

* KubeMQ server running on `localhost:50000`
* Java SDK installed (`implementation 'io.kubemq.sdk:kubemq-sdk-Java:3.1.1'` (Gradle) or Maven dependency from [Getting Started](/sdks/java))

## Code [#code]

```java title="AutoAckExample.java"
package io.kubemq.example.queuesstream;

import io.kubemq.sdk.queues.*;
import java.util.UUID;

/**
 * AutoAckExample for Queues Stream
 */
public class AutoAckExample {
    private static final String ADDRESS = "localhost:50000";
    private static final String CLIENT_ID = "java-queues-auto-ack-client";
    private static final String CHANNEL = "java-queues.auto-ack";

    public static void main(String[] args) {
        // Create a client connected to the KubeMQ server
        try (QueuesClient client = QueuesClient.builder().address(ADDRESS).clientId(CLIENT_ID).build()) {
            // Create the queue channel
            client.createQueuesChannel(CHANNEL);

            // Send messages to the queue
            for (int i = 1; i <= 3; i++) {
                client.sendQueueMessage(QueueMessage.builder()
                        .channel(CHANNEL).body(("Auto-ack msg " + i).getBytes()).build());
            }

            // Poll with auto-ack enabled (messages acknowledged automatically)
            System.out.println("Polling with autoAckMessages=true...\n");
            QueuesPollResponse response = client.receiveQueueMessages(QueuesPollRequest.builder()
                    .channel(CHANNEL).pollMaxMessages(10).pollWaitTimeoutInSeconds(5)
                    .autoAckMessages(true).build());

            response.getMessages().forEach(msg ->
                System.out.println("  Received (auto-acked): " + new String(msg.getBody())));
            System.out.println("\n" + response.getMessages().size() + " messages auto-acknowledged.");

            // Clean up resources
            client.deleteQueuesChannel(CHANNEL);
        } catch (Exception e) {
            System.err.println("Error: " + e.getMessage());
        }
    }
}

```

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

* `autoAckMessages(true)` in `QueuesPollRequest` instructs the broker to acknowledge each message immediately upon delivery; no explicit `msg.ack()` call is needed.
* This is the lowest-effort receive pattern but provides at-most-once delivery — if the consumer crashes after receiving but before processing, the message is lost.
* Use `autoAckMessages(false)` (the default) for at-least-once guarantees where you call `msg.ack()` only after successful processing.

## Related [#related]

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