← All articles

Backend & Data

Message queues vs streams

2026-07-20 · 6 min read

A queue and a stream both let one part of your system hand work to another without waiting. That's where the similarity ends. A queue is a to-do list: each item is taken by one worker and then it's gone. A stream is a logbook: messages are appended and kept, and any number of readers can go through them at their own pace — and re-read the past. Picking the wrong one leads to a lot of pain.

Consumed-once vs kept-forever

A queue versus a stream Queue · taken, then gone Producer Worker one message → one worker, removed Stream · an append-only log Producer e1 e2 e3 e4 reader A reader B kept · each reader has its own position
A queue deletes a message once a worker takes it. A stream keeps it, so many consumers can read — and re-read — independently.

Message queue — hand off work

Classic queues (RabbitMQ, SQS) exist to distribute tasks. A producer drops a job on the queue; whichever worker grabs it first does it, acknowledges, and the message disappears. Add workers to go faster; the queue spreads the load. It's perfect for "do this thing once" — send an email, resize an image, process a payment. What it doesn't give you: history. Once a message is consumed, it's gone.

Stream — a replayable log

A stream (Kafka, Redis Streams) is an append-only log. Messages are written in order and retained. Consumers track their own position, so several independent systems can read the same events — and a new consumer can start from the beginning and replay all of history. It's built for "many things care about this event" — analytics, auditing, syncing multiple services, event sourcing.

The gist

Queue = a shared to-do list; take a task and it's off the list. Stream = a logbook; everyone reads it at their own pace and the entries stay. Delete-on-read vs keep-and-replay.

Which to reach for

  • Use a queue when a job needs doing exactly once by one worker, and you don't care about it afterwards.
  • Use a stream when multiple consumers need the same events, when you need to replay history, or when order and retention matter.
  • Both pair with resilience patterns — acknowledge work so nothing is lost, and wrap flaky consumers in circuit breakers and backoff.

The one-line test: if the answer to "who needs this message?" is "exactly one worker, once," you want a queue. If it's "several readers, maybe including some that don't exist yet," you want a stream.


Message queueStreamsKafkaBackend
← Back to the blog