AcknowledgeMode.AUTO (Most common in production)
Spring handles acknowledgment automatically:
- ✔ ACK is sent only after your
@RabbitListener method finishes successfully
- ✔ If your code throws an exception → message is NACKed + requeued or sent to DLQ
- ✔ Protects from message loss
- ✔ Perfect for microservices and business events
- ✔ Minimal code, but still reliable
This is the default behavior in Spring Boot—no special config needed.
🟩 1A. Real-world use cases for AUTO
| Example |
Why AUTO works well |
| Order created event |
If consumer fails → retry safely |
| Email notification service |
Failed sends → DLQ |
| Inventory update microservice |
Spring handles NACK automatically |
| Billing receipt processor |
Reliable, no custom retry logic needed |
🟦 1B. Spring Boot Example (AcknowledgeMode.AUTO)
👉 No manual ACK required
👉 Throwing exception triggers Spring to NACK the message
@Service
public class AutoAckConsumer {
@RabbitListener(queues = "order.queue") // AUTO is default
public void handleOrder(String message) {
System.out.println("Received order: " + message);
if (message.contains("fail")) {
throw new RuntimeException("Processing failed!");
}
// If this method completes normally → Spring automatically sends ACK
}
}
Behavior:
- If message = "order123" → Spring ACKs it
- If message = "order-fail" → Spring automatically NACKs + requeues (or DLQs)
You get reliability without extra code.
🟥 2. AcknowledgeMode.MANUAL (Used for high-control systems)
The consumer is responsible for basicAck, basicNack, basicReject.
- ✔ Gives full control
- ✔ Prevents infinite retry loops
- ✔ Allows partial batch processing
- ✔ Needed when you want EXACT retry logic (e.g., retry 5 times then DLQ)
- ✔ Common in financial, billing, inventory, and high-volume pipelines
🟩 2A. Real-world use cases for MANUAL
| Example |
Why MANUAL is needed |
| Payment processing |
Never retry indefinitely |
| Stock trading messages |
Strict handling, manual control |
| Inventory sync jobs |
Batch-level ACKs |
| Fraud detection pipeline |
Custom DLQ logic |
| High-volume log ingestion |
Manual backpressure control |
🟥 2B. Spring Boot Example (AcknowledgeMode.MANUAL)
Step 1 — Configure listener factory
@Configuration
public class RabbitConfig {
@Bean
public SimpleRabbitListenerContainerFactory manualAckFactory(ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
return factory;
}
}
Step 2 — Manual ack consumer
@Service
public class ManualAckConsumer {
@RabbitListener(queues = "payment.queue", containerFactory = "manualAckFactory")
public void handlePayment(Message message, Channel channel) throws Exception {
long tag = message.getMessageProperties().getDeliveryTag();
String body = new String(message.getBody());
System.out.println("Processing payment: " + body);
try {
// Simulate failure
if (body.contains("fail")) {
throw new RuntimeException("Payment error");
}
// SUCCESS → ACK
channel.basicAck(tag, false);
System.out.println("ACK sent");
} catch (Exception e) {
// FAILURE → send to DLQ manually (example)
System.out.println("Sending to DLQ: " + body);
channel.basicReject(tag, false); // false means: do NOT requeue
}
}
}
Behavior:
- Success → ACK
- Failure → manually REJECT to DLQ
- No infinite retry loops
- No accidental reprocessing
This is the pattern used in serious enterprise systems.