Kafka is not a task queue

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. ...

September 11, 2026 · 2 min · Murat Useinov

Redis Streams is a log, not a better queue

“Should we move the queue to Streams? They are the proper way now.” A colleague, this week, about our Redis list queue. Wrong question. Streams are not a newer version of the same thing. A list queue is a hand-off. LPUSH on one side, BRPOP on the other, and once a consumer takes the message, it is gone. Crash after the pop and the message died with you, unless you built the pending-list dance yourself. No history, no second reader. For “send this email eventually” it is honestly enough. ...

August 20, 2021 · 2 min · Murat Useinov

The outbox table

About once a month an order existed and nobody heard about it. The order service saved the order, then published order.created to RabbitMQ, and once a month the process died between the two. Rare enough to be mysterious. Frequent enough to ruin a weekend. Two operations, two systems, no common transaction. Whatever order you do them in, you lose. Commit first, then publish: the order exists, the event never leaves. Publish first, then commit: the commit fails, consumers are already busy with an order that does not exist. We had the first variant in production. ...

March 23, 2021 · 2 min · Murat Useinov