How it works
The explanation, with examples you can run.
Side by side
| Kafka (consumer groups) | Work queue (RabbitMQ queues, SQS) | |
|---|---|---|
| After processing | Record stays until retention | Message is deleted on acknowledgement |
| Many independent readers | Each group reads everything | Fan out to one queue per subscriber (exchanges, SNS) |
| Replay | Reset offsets within retention | Not possible once deleted |
| Ordering | Per partition, by key | Usually none (SQS FIFO and single-consumer queues are exceptions) |
| Parallelism | Up to the partition count per group | Add consumers freely |
| Unit of acknowledgement | An offset per partition | One message |
| A slow or poison message | Holds up its partition | Others carry on; it is retried or dead-lettered |
| Routing | Topic and key | Rich in RabbitMQ (exchanges, bindings); simple in SQS |
| Retention | Configurable: hours, days or forever | Until consumed; SQS also expires messages after 4 days by default, 14 at most |
When Kafka fits
- Events that several systems consume, now or later: order placed, payment captured, profile changed.
- Replay and backfill: rebuilding a search index, recomputing analytics after a bug fix, onboarding a new service from history.
- Streams processing and change data capture, where ordering per key matters.
- High sustained throughput with consumers that read in batches.
When a queue fits
- Task distribution: send this email, resize this image, call this webhook. Jobs vary in duration, ordering does not matter, and one stuck job should not delay the rest.
- Per-message retries with delays and dead letter queues, without writing that machinery yourself.
- Request/reply and routing patterns, where RabbitMQ's exchanges do the work.
- Small volumes where running a Kafka cluster (or paying for a managed one) is not worth it; SQS is serverless and pay per request.
Share groups: queues inside Kafka
Kafka 4.2 made share groups (KIP-932, "queues for Kafka") production-ready. Consumers in a share group take records from the same partitions cooperatively instead of owning whole partitions. Each record is acquired with a time-limited lock (share.record.lock.duration.ms, 30 s by default), acknowledged individually, and redelivered if not, up to share.delivery.count.limit attempts (5 by default). That suits queue-shaped work on data that already lives in Kafka, without ordering guarantees. It is new, so check client support in your language before relying on it.
Both, often
Many systems use both: Kafka as the record of what happened, and queues (or share groups) for the tasks those events cause. In either case delivery is at least once, so the handlers are idempotent.
Check yourself
3 questions. Get them all right to finish this topic.
0 of 3 right so far. Get all three to finish this topic.