What Happens to Unacked Messages in RabbitMQ Explained
In RabbitMQ, an
unacked message is one that has been delivered to a consumer but not yet acknowledged. If the consumer disconnects or crashes before acknowledging, the message is requeued and delivered to another consumer to ensure it is processed.Syntax
RabbitMQ uses message acknowledgements to confirm that a message was received and processed by a consumer. The key parts are:
basic.deliver: RabbitMQ sends a message to a consumer.basic.ack: The consumer sends this to acknowledge successful processing.unacked: Messages delivered but not yet acknowledged.
If a message remains unacked, RabbitMQ waits for an acknowledgement or consumer failure.
java
channel.basicConsume(queueName, false, new DefaultConsumer(channel) { @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { // Process message // Acknowledge after processing channel.basicAck(envelope.getDeliveryTag(), false); } });
Example
This example shows a consumer receiving a message and not acknowledging it immediately. The message stays unacked until the consumer sends an acknowledgement or disconnects.
java
import com.rabbitmq.client.*; public class UnackedExample { private final static String QUEUE_NAME = "test_queue"; public static void main(String[] argv) throws Exception { ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); try (Connection connection = factory.newConnection(); Channel channel = connection.createChannel()) { channel.queueDeclare(QUEUE_NAME, false, false, false, null); System.out.println("Waiting for messages. To exit press CTRL+C"); channel.basicConsume(QUEUE_NAME, false, new DefaultConsumer(channel) { @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { String message = new String(body, "UTF-8"); System.out.println("Received: " + message); // Intentionally not acknowledging here // Message remains unacked } }); // Keep program running to observe unacked message Thread.sleep(60000); } } }
Output
Waiting for messages. To exit press CTRL+C
Received: Hello RabbitMQ!
Common Pitfalls
Common mistakes with unacked messages include:
- Not sending
basic.ackafter processing, causing messages to stay unacked and block queue resources. - Consumer crashes or disconnects without ack, which causes RabbitMQ to requeue the message, possibly leading to duplicate processing.
- Using
autoAck=true(automatic acknowledgement) which can cause message loss if the consumer fails before processing.
Always acknowledge messages after successful processing to avoid these issues.
java
channel.basicConsume(queueName, true, consumerTag, consumer); // autoAck=true (not recommended) // Correct way: channel.basicConsume(queueName, false, consumerTag, consumer); // Then call channel.basicAck(deliveryTag, false) after processing
Quick Reference
| Term | Description |
|---|---|
| unacked | Message delivered but not yet acknowledged by consumer |
| basic.ack | Consumer confirms successful processing of a message |
| requeue | Message returned to queue if consumer disconnects before ack |
| autoAck | Automatic acknowledgement mode, risky for message loss |
| deliveryTag | Unique ID for message delivery used in acknowledgements |
Key Takeaways
Unacked messages remain with the consumer until acknowledged or consumer failure.
If a consumer disconnects without ack, RabbitMQ requeues the message for redelivery.
Always use manual acknowledgements (autoAck=false) to avoid message loss.
Not acknowledging messages can block queue resources and reduce throughput.
Proper ack handling ensures reliable message processing and avoids duplicates.