Acknowledgements: auto-ack is a data-loss switch

RabbitMQ Course · lesson 4 of 15 · 5 min read

Manual ack is what makes at-least-once delivery real, and it changes the states a message can be in.

Open this lesson in the learning hub

Key points

  • Auto-ack acks at delivery time, so a consumer crash mid-work loses the message for good.
  • Manual ack means basic.ack after the work succeeded, not when the handler starts.
  • basic.nack is a RabbitMQ extension: unlike basic.reject it can reject many delivery tags at once.
  • Unacked messages are tracked per channel, so closing that channel requeues every one of them.
  • RabbitMQ 3.8.15 added consumer_timeout; the default is 30 minutes and it closes the channel.
  • Delivery tags are per channel and increase monotonically - never ack a tag on another channel.

Example

boolean autoAck = false;                     // the important argument
ch.basicQos(20);                             // never consume without this

ch.basicConsume("invoicing", autoAck, (tag, delivery) -> {
    long deliveryTag = delivery.getEnvelope().getDeliveryTag();
    try {
        invoiceService.handle(delivery.getBody());
        ch.basicAck(deliveryTag, false);      // false = just this one
    } catch (TransientException e) {
        ch.basicNack(deliveryTag, false, true);   // requeue: try again
    } catch (PermanentException e) {
        ch.basicNack(deliveryTag, false, false);  // to the DLX, not back
    }
}, tag -> { });

Ack after the work, nack with requeue false plus a DLX for anything that will never succeed.

This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the RabbitMQ Course course, and every lesson in it is listed on the RabbitMQ Course contents page.