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

**Gotchas:** if your consumer crashes or panics after `PollQueue` 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/go/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 your poll timeout are your only throttles — there's no visibility-timeout window to tune.

## Prerequisites [#prerequisites]

* KubeMQ server running on `localhost:50000`
* Go SDK installed (`go get github.com/kubemq-io/kubemq-go/v2`)

## Code [#code]

```go title="main.go"
// Example: queues-stream/auto-ack
//
// Demonstrates receiving queue messages with automatic acknowledgment.
// When AutoAck is true, messages are automatically acknowledged upon receipt.
//
// Channel: go-queues-stream.auto-ack
// Client ID: go-queues-stream-auto-ack-client
//
// Run with a KubeMQ server on localhost:50000
// (see https://docs.kubemq.io/deploy).
package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/kubemq-io/kubemq-go/v2"
)

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	client, err := kubemq.NewClient(ctx,
		kubemq.WithAddress("localhost", 50000),
		kubemq.WithClientId("go-queues-stream-auto-ack-client"),
	)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	channel := "go-queues-stream.auto-ack"

	// Send a message.
	_, err = client.SendQueueMessage(ctx, kubemq.NewQueueMessage().
		SetChannel(channel).
		SetBody([]byte("auto-ack message")))
	if err != nil {
		log.Fatal(err)
	}

	// Poll with AutoAck=true - messages are acknowledged automatically.
	pollResp, err := client.PollQueue(ctx, &kubemq.PollRequest{
		Channel:            channel,
		MaxItems:           10,
		WaitTimeoutSeconds: 5,
	})
	if err != nil {
		log.Fatalf("PollQueue: %v", err)
	}
	fmt.Printf("Auto-ack: received %d messages (automatically acknowledged)\n",
		len(pollResp.Messages))
	for _, dm := range pollResp.Messages {
		if dm.Message != nil {
			fmt.Printf("  body=%s\n", dm.Message.Body)
		}
	}
}

```

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

1. `client.PollQueue(ctx, &kubemq.PollRequest{...})` omits `AutoAck` (defaults to `true`), so the broker acknowledges each message automatically when it is delivered — no explicit ack is required.
2. Auto-ack is the simplest consumption model: messages are consumed atomically with their delivery and will not be redelivered even if the consumer crashes after receiving them.
3. Contrast with `AutoAck: false` (used in Ack & Reject, Ack All) where messages are held in a transaction and must be explicitly settled, enabling at-least-once retry on failure.
4. `len(pollResp.Messages)` reports how many messages were in the queue at poll time up to `MaxItems`.

## Related [#related]

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