Message Brokers Comparison: RabbitMQ vs Kafka vs ActiveMQ
A comprehensive comparison of three popular message brokers for distributed systems.
Overview
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Message Broker Landscape β
ββββββββββββββββ¬βββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββ€
β RabbitMQ β Kafka β ActiveMQ β
ββββββββββββββββΌβββββββββββββββββββββΌβββββββββββββββββββββββββββββββββ€
β Traditional β Distributed β JMS-compliant β
β Message β Streaming β Enterprise β
β Broker β Platform β Message Broker β
ββββββββββββββββ΄βββββββββββββββββββββ΄βββββββββββββββββββββββββββββββββ
RabbitMQ
Architecture
ββββββββββββββββββββββββββββββββββββββββββββββββββββ
β RabbitMQ β
ββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Producer βββΆ Exchange βββΆ Queue βββΆ Consumer β
β β β
β Bindings β
β (routing rules) β
β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββ
Key Features
- AMQP Protocol: Standard messaging protocol
- Exchange Types: Direct, Topic, Fanout, Headers
- Message Acknowledgments: Reliable delivery
- Flexible Routing: Complex routing patterns
- Plugins: Extensive plugin ecosystem
- Management UI: Built-in web interface
Exchange Types
Direct Exchange:
Producer ββ"order.created"βββΆ Exchange βββΆ Queue (order.created)
Topic Exchange:
Producer ββ"order.*.created"βββΆ Exchange βββΆ Queue (order.usa.created)
βββΆ Queue (order.eu.created)
Fanout Exchange:
Producer ββmessageβββΆ Exchange βββΆ All bound queues
C# Example (using RabbitMQ.Client)
// Producer
var factory = new ConnectionFactory { HostName = "localhost" };
using var connection = factory.CreateConnection();
using var channel = connection.CreateModel();
channel.ExchangeDeclare("orders", ExchangeType.Topic, durable: true);
channel.QueueDeclare("order-processing", durable: true, exclusive: false);
channel.QueueBind("order-processing", "orders", "order.created");
var body = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(order));
channel.BasicPublish(
exchange: "orders",
routingKey: "order.created",
body: body
);
// Consumer
channel.BasicConsume("order-processing", autoAck: false, consumer: new EventingBasicConsumer(channel)
{
Received = (model, ea) =>
{
var body = ea.Body.ToArray();
var message = Encoding.UTF8.GetString(body);
ProcessOrder(message);
channel.BasicAck(ea.DeliveryTag, multiple: false);
}
});
Best For
- Complex routing requirements
- Request/Reply patterns
- Traditional message queuing
- RPC-style communication
- Guaranteed delivery with acknowledgments
Apache Kafka
Architecture
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Kafka Cluster β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Topic: orders β β
β ββββββββββββ¬βββββββββββ¬βββββββββββ¬βββββββββββββββββββ¬ββ€ β
β βPartition βPartition βPartition β ... β β β
β β 0 β 1 β 2 β β β β
β ββββββββββββ΄βββββββββββ΄βββββββββββ΄βββββββββββββββββββ΄ββ β
β β
β Producers βββββΆ Partitions βββββΆ Consumer Groups β
β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Key Features
- High Throughput: Millions of messages per second
- Distributed Log: Append-only, immutable
- Partitioning: Horizontal scalability
- Replication: Fault tolerance
- Consumer Groups: Parallel processing
- Long Retention: Event sourcing capable
- Stream Processing: Kafka Streams, ksqlDB
Partition Strategy
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Partition Assignment β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Key-based: hash(order_id) % num_partitions β
β β
β Order 123 βββΆ Partition 0 β
β Order 456 βββΆ Partition 1 β
β Order 789 βββΆ Partition 2 β
β β
β Guarantees: Same key = Same partition = Ordering β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
C# Example (using Confluent.Kafka)
// Producer
var config = new ProducerConfig { BootstrapServers = "localhost:9092" };
using var producer = new ProducerBuilder<string, string>(config).Build();
await producer.ProduceAsync("orders", new Message<string, string>
{
Key = order.Id, // Ensures ordering per order
Value = JsonSerializer.Serialize(order)
});
// Consumer
var consumerConfig = new ConsumerConfig
{
BootstrapServers = "localhost:9092",
GroupId = "order-processors",
AutoOffsetReset = AutoOffsetReset.Earliest
};
using var consumer = new ConsumerBuilder<string, string>(consumerConfig).Build();
consumer.Subscribe("orders");
while (true)
{
var message = consumer.Consume();
ProcessOrder(message.Value);
consumer.Commit(message);
}
Best For
- High-throughput event streaming
- Event sourcing architectures
- Log aggregation
- Real-time analytics
- Replay of historical events
- Microservices event bus
ActiveMQ
Architecture
ββββββββββββββββββββββββββββββββββββββββββββββββββββ
β ActiveMQ β
ββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β JMS Producer βββΆ Destination βββΆ JMS Consumer β
β β β
β Queue (P2P) β
β Topic (Pub/Sub) β
β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββ
Key Features
- JMS Compliance: Java enterprise standard
- Multiple Protocols: AMQP, STOMP, OpenWire, MQTT
- Persistence: KahaDB, JDBC
- Clustering: Network of brokers
- Virtual Destinations: Composite destinations
- Message Groups: Related message processing
Destination Types
Queue (Point-to-Point):
Producer βββΆ Queue βββΆ Single Consumer
Topic (Publish/Subscribe):
Publisher βββΆ Topic βββΆ Subscriber 1
βββΆ Subscriber 2
βββΆ Subscriber N
Configuration Example
<!-- activemq.xml -->
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost">
<destinationPolicy>
<policyMap>
<policyEntries>
<policyEntry queue="orders.*" producerFlowControl="true"/>
</policyEntries>
</policyMap>
</destinationPolicy>
<persistenceAdapter>
<kahaDB directory="${activemq.data}/kahadb"/>
</persistenceAdapter>
</broker>
Best For
- JMS-based enterprise applications
- Legacy system integration
- Multi-protocol support requirements
- Traditional enterprise messaging
Comparison Matrix
| Feature | RabbitMQ | Kafka | ActiveMQ |
|---|---|---|---|
| Throughput | Medium (~50k/s) | Very High (~1M/s) | Medium (~50k/s) |
| Latency | Low (ms) | Medium (ms) | Low (ms) |
| Message Order | Per queue | Per partition | Per queue |
| Delivery | At-least-once, exactly-once | At-least-once, exactly-once | At-least-once |
| Retention | Until consumed | Time/size based | Until consumed |
| Protocol | AMQP | Kafka Protocol | JMS, AMQP, STOMP |
| Routing | Rich (exchanges) | Simple (topics) | Moderate |
| Replay | No | Yes | No |
| Clustering | Built-in | Native | Network of brokers |
Decision Guide
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β When to Use Which Broker? β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Need complex routing? βββΆ RabbitMQ β
β Need request/reply pattern? βββΆ RabbitMQ β
β β
β Need high throughput? βββΆ Kafka β
β Need event replay? βββΆ Kafka β
β Need stream processing? βββΆ Kafka β
β β
β Need JMS compliance? βββΆ ActiveMQ β
β Need multi-protocol? βββΆ ActiveMQ β
β Legacy Java integration? βββΆ ActiveMQ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Performance Characteristics
Throughput Comparison
Messages/second (approximate):
Kafka: ββββββββββββββββββββββββββββββββββββ 1,000,000+
RabbitMQ: ββββββ 50,000
ActiveMQ: ββββββ 50,000
Latency Comparison
Average latency:
RabbitMQ: ββ 1-2ms
ActiveMQ: βββ 2-3ms
Kafka: βββββ 5-10ms (but higher throughput)
Hybrid Architectures
Often, production systems use multiple brokers:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Hybrid Architecture β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β RabbitMQ ββββββββββΆ Request/Reply, Complex routing β
β β β
β βΌ β
β Kafka βββββββββββΆ Event streaming, Analytics β
β β β
β βΌ β
β ActiveMQ ββββββββββΆ Legacy JMS integration β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Sources
Arhitectura/rabbitmq vs kafka vs activemq.gif