Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Spring AMQP prefetch: bound unacknowledged messages before raising concurrency

Last updated: 1 Oct 20264 min read
tutorial
IntermediateBy AITrove Editorial

Rabbit listener prefetch controls how many messages a consumer can hold without acknowledgment, not how many it has committed.

Count in-flight bytes

A parcel-photo event can carry 420 KiB of metadata and thumbnails. With prefetch 250, one consumer may hold roughly 103 MiB of payload before object overhead; four concurrent consumers can multiply that pressure. Lower prefetch when messages are large, handlers are slow or strict ordering matters. An executor limit does not remove messages already delivered to listener containers.

Tie acknowledgement to the effect

A listener may commit a database change and lose its connection before the broker records the acknowledgment. The event can be redelivered, even with a low prefetch. Keep the dedup key and business write in one database transaction. Prefetch is capacity control, not exactly-once processing.

Measure under a stalled handler

Run two consumers, block one handler, publish 47 messages, and measure unacknowledged count, heap use and distribution. Lower prefetch until memory and fairness meet the service budget. The property sketch assumes a simple listener container; a direct container or per-listener factory needs its own configuration check.

Implementation sketch

yaml
spring:
  rabbitmq:
    listener:
      simple:
        prefetch: 23
        concurrency: 2
        max-concurrency: 4

Cost and verification

Smaller prefetch limits memory and can improve fairness, but adds broker round trips and may lower throughput. Measure with production-sized messages.

Common Mistakes

  • Do not equate prefetch with completed transactions.
  • Do not raise concurrency without accounting for prefetch times message size.
  • Do not assume prefetch one prevents redelivery after a lost acknowledgment.

Read next

Spring AMQP poison messages: reject, requeue and dead-letter are different decisions, Spring consumer deduplication: commit the event ID with the mutation, Spring Kafka manual acknowledgement: commit work before advancing the offset, Spring task executors: reject work when every slot is occupied.

spring
spring-production
rabbit-prefetch-memory
Storage details