Most of what circulates about RabbitMQ's limitations was accurate around 2015 and has not been updated since. That matters more than it sounds, because these claims get repeated in comparison articles, repeated again in architecture decision records, and eventually decide real infrastructure spend.
None of what follows is an argument that RabbitMQ is always the right answer. We run both RabbitMQ and Kafka in production and there are workloads where Kafka is clearly correct. It is an argument for choosing on current facts rather than on inherited ones.
1. "Kafka for streaming, RabbitMQ for queuing"
This was a genuinely good rule of thumb. It is now the single most misleading thing said about either system.
RabbitMQ has had streams since 3.9 — a persistent, replayable append-only log with non-destructive reads and consumer-tracked offsets. Kafka added share groups, giving it queue-like consumption where multiple consumers pull from a topic without partition-exclusive assignment. Both systems now cover both jobs.
That does not make them interchangeable. It means the decision moved from which one can do this to which one does it well under load and at what operational cost, which is a harder and more useful question. Anyone still opening with the old split is answering a question from a decade ago.
2. "RabbitMQ can't handle high throughput"
RabbitMQ streams reach several million messages per second on comparable hardware — the same class as Kafka. The designs converged deliberately: batching into chunks, one binary format from producer through disk to consumer, zero-copy reads via sendfile, page cache instead of application heap.
Benchmarks still showing RabbitMQ an order of magnitude behind are almost always measuring classic queues against Kafka topics, which compares a work-distribution mechanism to a log.
The honest version of this concern: a single quorum queue tops out around 80,000 messages per second with replication and fsync, and it is not sharded — you cannot split one queue across nodes the way a Kafka topic splits across partitions. Aggregate throughput across many queues scales fine. But if you genuinely need one flow through one destination faster than that, Kafka's partitioning wins. That is a real limitation, and it is not the one the myth describes.
3. "RabbitMQ needs a lot of RAM because it keeps messages in memory"
This was a fair characterisation of older classic queue behaviour, and it produced a lasting reputation for memory sensitivity.
Streams use the operating system page cache rather than holding messages in application heap — the same approach Kafka takes. Quorum queues write to a shared write-ahead log. Memory behaviour is one of the areas that changed most between RabbitMQ 3.x and 4.x.
The nuance worth keeping: a quorum queue does hold more memory per queue than a classic queue, because it carries Raft state. If you run thousands of small queues and convert them all at once, that is a real memory consideration — which we cover in classic vs quorum queues. That is a migration-planning issue, not a general memory problem.
4. "RabbitMQ deletes messages as soon as they're read"
True of classic and quorum queues, and correct behaviour for them — reads are destructive because a work queue should hand each job to exactly one worker.
Streams are the opposite. Reads are non-destructive. Consumers attach at an offset and read forward, the data stays available, and ten independent applications can each read every message and replay from the beginning whenever they need to.
This is the misconception we correct most often, and it has real consequences: teams conclude they need Kafka for event history when the broker they already run does it. If you find yourself wanting to re-read messages from a queue, you want a stream.
5. "Only Kafka can do exactly-once processing"
Worth being precise here, because the terminology causes half the confusion. True exactly-once delivery is not achievable in a distributed system. What both systems offer is better described as effectively-once: the result is applied once, even if delivery happens more than once.
Kafka provides this for read-process-write loops — consume from one partition, process, produce to another, with the whole thing applied once. RabbitMQ streams can provide the same guarantee for equivalent pipelines.
So the differentiator is not the guarantee. It is the surrounding ecosystem: Kafka Streams gives you joins, windowing and aggregations as a library, and that tooling gap is real and worth choosing Kafka for. The guarantee itself is not exclusive.
6. "Erlang is a liability"
The usual form of this: nobody on the team knows Erlang, so the runtime is a risk.
For messaging middleware specifically, the BEAM runtime is closer to an advantage. It was designed for always-on telecoms systems, and it gives RabbitMQ fault isolation that matters in production: a crashing queue or connection takes down its own lightweight process while the rest of the node continues. We have seen incidents where a single queue crash-looped in isolation and nothing else in the system was affected — on a runtime without that property, the same fault profile is a node-level problem.
It also supports very high concurrency without application-level locking, which is why RabbitMQ handles large MQTT connection counts well. The JVM is excellent general-purpose server software; BEAM is specialised for exactly this shape of problem.
The legitimate concern underneath the myth is hiring and familiarity, not runtime quality. Deep RabbitMQ debugging occasionally means reading Erlang, and that skill is rarer than JVM skill. That is a genuine reason to have a support arrangement — not a reason to avoid the broker.
What RabbitMQ Is Actually Good At
Debunking is only half useful. Here is the positive case, which the myths tend to crowd out.
RabbitMQ is a message broker first. Its core job is moving discrete units of work between applications, and it is unusually good at the parts of that job which are tedious to build yourself: per-message TTL, strict priority levels, dead-letter routing, delayed retries, and acknowledgement tracked on the broker rather than in your code. Any message queue can move bytes. Those features are what stop a work queue from becoming a distributed systems project.
Routing is done on the broker. Exchanges and bindings decide where a message goes, and they are reconfigurable at runtime. Adding a consumer to an existing flow is a configuration change rather than a code change and redeploy — which matters a great deal once you have more than a handful of use cases sharing one messaging system. We cover that in exchanges vs partitions.
It speaks more than one protocol. A single RabbitMQ server cluster serves AMQP 1.0, AMQP 0-9-1, MQTT, STOMP and JMS, so IoT devices, Java applications and microservices can share one broker instead of one broker plus a set of bridges. For a mixed estate that is a genuine reduction in moving parts.
It is scalable in the direction most enterprises actually need. Not one enormous data stream, but many thousands of cheap queues with per-tenant isolation through virtual hosts. That is the shape of most real messaging estates, and it is the shape Kafka handles least gracefully.
Use RabbitMQ when messages are work items. Use Kafka when messages are a log. Most organisations have both, which is why running the two side by side is a legitimate architecture rather than a failure to decide.
What Is Actually True
Retiring bad reasons makes room for the real ones. The current, legitimate reasons to choose Kafka over RabbitMQ:
- Tiered storage. Offloading old segments to object storage makes multi-year retention economical. RabbitMQ has no equivalent.
- Log compaction. Latest-value-per-key is native to Kafka.
- Stream processing ecosystem. Kafka Streams and its connectors are substantially more mature.
- One extremely hot flow. Partitioning shards a topic; a quorum queue does not shard.
Those four are worth arguing about. The six above are not.
If you are making this decision against a real workload and want it assessed on current facts, talk to AceMQ. We are equally happy to tell you the answer is Kafka.
FAQ
Is RabbitMQ slow compared to Kafka?
Not for streaming. RabbitMQ streams reach several million messages per second, comparable to Kafka, because the designs converged on the same techniques. The real ceiling is a single quorum queue at around 80,000 messages per second with replication and fsync, because it is not sharded — a per-destination limit, not a system-wide one.
Why do people say not to use RabbitMQ?
Most reasons circulating are a decade out of date — that it cannot handle throughput, holds everything in memory, or deletes messages once read. The legitimate current reasons are specific: tiered storage, log compaction, a mature stream processing ecosystem, or pushing one single flow past what an unsharded queue carries.
Does RabbitMQ still keep all messages in RAM?
No. Streams use the operating system page cache rather than application heap, the same approach Kafka uses, and quorum queues write to a shared write-ahead log. Memory behaviour changed substantially between RabbitMQ 3.x and 4.x.
Does RabbitMQ delete messages as soon as they are read?
Classic and quorum queues do — destructive reads are correct for work distribution. Streams do not: reads are non-destructive, consumers track their own offset, and many independent consumers can read the same history and replay from the beginning.
Can only Kafka do exactly-once processing?
No. The accurate term in both systems is effectively-once. Kafka provides it for read-process-write loops between partitions; RabbitMQ streams provide the same guarantee for equivalent pipelines. The real Kafka advantage is the surrounding stream processing tooling, not the guarantee.
Is Erlang a liability for RabbitMQ?
Closer to the opposite. The BEAM runtime is built for always-on systems and gives fault isolation that matters in production — a crashing queue or connection takes down its own process rather than the node. It also supports high concurrency without application-level locking. The real consideration is hiring and familiarity, not runtime quality.