Kafka, RabbitMQ and SQS all move messages between services, which is why teams argue about them as if it’s a preference. It isn’t. They differ on one structural question: who owns the record of what has been read.
Kafka keeps the log, you keep your place in it. Messages aren’t consumed, they’re retained for a window and every consumer tracks its own offset. That’s what makes replay possible: a new service can start from last Tuesday and rebuild its state from events that already happened, and an analytics consumer falling behind doesn’t affect the recommendation consumer at all. You pay for that with operational weight and with partitions, because ordering is per partition and your partition key quietly becomes a design decision you’ll live with.
RabbitMQ owns delivery, and hands you routing. The broker decides where a message goes based on rules you define, tracks acknowledgements, and removes the message once it’s done. That’s the right shape for work that needs to happen once: video encoding, emails, anything where you care that a specific task completed and want it retried or dead-lettered if it didn’t. Replay isn’t the model. Once it’s acked, it’s gone.
SQS owns all of it, including the servers. Same consumption model as Rabbit, far less control, and nothing to operate. If you’re already on AWS and the requirement is “run this work later, don’t lose it”, the honest answer is usually that anything more capable is a cost you haven’t justified yet.
So the question isn’t which is best. It’s whether you need to re-read history later, or just need work to happen once. Kafka answers the first. The other two answer the second, and SQS answers it without a cluster to keep alive.
Which means the real mistake isn’t choosing Kafka. It’s choosing Kafka for a task queue, then discovering you now run a distributed log so that a worker can resize images.