title: Spring AMPQ multiple consumers vs higher prefetch value
body: <p>Even after reading plenty of SO questions (<a href="https://stackoverflow.com/questions/37015650/spring-amqp-single-consumer-parallelism-with-prefetch">1</a>,<a href="https://stackoverflow.com/questions/39699727/what-is-the-difference-between-prefetch-count-vs-no-ack-in-rabbitmq">2</a>) and articles, It is unclear on which is the better option to set for consumers. Multiple consumers or a higher prefetch value? </p>
  
  <p>From what I understand, when it comes to <code>SimpleRabbitListenerContainerFactory</code>, <del>as it was designed initially to have only one thread per connection</del> it was designed to address a limitation that the amqp-client only had one thread per connection, does that mean that setting multiple consumers won't make much difference as there is only one thread that actually consumes from rabbit and than hands it off to the multiple consumers (threads)?
  Or there are actually several consumers consuming at the same time?</p>
  
  <p>So what is the best practice when it comes to spring implementation of rabbit concerning prefetch/consumers? When should one be used over the other? And should I switch to this new <code>DirectRabbitListenerContainerFactory</code>? Is it 'better' or just depends on the use case?</p>
  
  <p>Some downsides I see when it comes to high prefetch is that maybe it can cause memory issues if an app consumes more messages that it can hold in the buffer? (haven't actually tested this yet, tbh)</p>
  
  <p>And when it comes to multiple consumers, I see the downside of having more file descriptors opened on OS level and I saw <a href="https://www.rabbitmq.com/blog/2012/05/11/some-queuing-theory-throughput-latency-and-bandwidth/" rel="nofollow noreferrer">this</a> article about that each consumer actually pings rabbit for each ack and this making it slower.</p>
  
  <p>FYI, if it is relevant, I usually have my config set up like this:</p>
  
  <pre><code>@Bean
  public ConnectionFactory connectionFactory() {
  final CachingConnectionFactory connectionFactory = new CachingConnectionFactory(server);
  connectionFactory.setUsername(username);
  connectionFactory.setPassword(password);
  connectionFactory.setVirtualHost(virtualHost);
  connectionFactory.setRequestedHeartBeat(requestedHeartBeat);
  return connectionFactory;
  }
  
  @Bean
  public AmqpAdmin amqpAdmin() {
      AmqpAdmin admin = new RabbitAdmin(connectionFactory());
      admin.declareQueue(getRabbitQueue());
      return admin;
  }
  
  @Bean
  public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory() {
  final SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
  factory.setConnectionFactory(connectionFactory());
  factory.setConcurrentConsumers(concurrency);
  factory.setMaxConcurrentConsumers(maxConcurrency);
  factory.setPrefetchCount(prefetch);
  factory.setMissingQueuesFatal(false);
  return factory;
  }
  
  @Bean
  public Queue getRabbitQueue() {
  final Map&lt;String, Object&gt; p = new HashMap&lt;String, Object&gt;();
  p.put("x-max-priority", 10);
  return new Queue(queueName, true, false, false, p);
  }
  </code></pre>