Building block
Message queue
A buffer between whoever creates work and whoever does it. It lets you answer the user right away and do the heavy job in the background with retries.
Why a queue
An author uploads a 2 GB video to ShortLesson. Transcoding into several qualities takes minutes, and you cannot keep an HTTP request open that long. The API puts a TranscodeVideo {id: 42} message on a queue and answers «processing» in 50 ms, and a worker picks up the job when it has free capacity.
A queue also smooths spikes. After a newsletter to 100 thousand people the API may accept 5 thousand signups a minute, and workers calmly send welcome emails over 10 minutes without exceeding the mail provider's limits.
Queue versus log: RabbitMQ versus Kafka
A classic queue (RabbitMQ, Amazon SQS) hands each message to one consumer and deletes it after acknowledgment (ack). It fits tasks: «do this once».
A log (Kafka, Redis Streams, Pulsar) keeps messages for a set time, and each consumer group reads from its own position (offset). Several independent systems can read the same events and even replay history. It fits event streams.
Retries, DLQ and idempotency
If a worker crashes mid task, a message without an ack returns to the queue (in SQS after the visibility timeout). So the same job can run twice, and the handler must be idempotent: check whether the video is already processed before doing the work.
A message that fails again and again (a broken file) moves to a dead letter queue after N attempts (say, 5). A human looks at it there, and the main queue is not blocked. Use exponential backoff between attempts: 1 s, 2 s, 4 s, 8 s.
Watch queue depth and the age of the oldest message. A queue that has been growing for an hour means too few workers or stuck ones.
Pros
- A fast answer to the user, heavy work in the background.
- Smooths spikes and protects slow dependencies.
- Retries and a DLQ instead of lost jobs.
- Workers scale separately from the API.
Cons
- «At least once» delivery requires idempotent handlers.
- Results are not immediate: you need a status or a notification.
- Another piece of infrastructure with depth and lag monitoring.
- Message ordering is not always guaranteed.
When to choose it
- A job takes longer than a few seconds (video, PDF, import).
- You need to call a slow or flaky external API.
- Load arrives in spikes.
- Work must be guaranteed to complete even through failures.
Tools
- RabbitMQRabbitMQ is a mature message broker with flexible routing through exchanges, acknowledgements and AMQP support.
- Amazon SQSAmazon SQS is a fully managed message queue from AWS that scales automatically and needs no servers.
- Apache KafkaKafka is a distributed event log for high-throughput data streaming with durable storage.
- Redis StreamsRedis Streams is a Redis data type shaped like an event log with consumer groups, usable as a light message queue.
- NATSNATS is a lightweight, very fast messaging system written in Go with pub/sub, request-reply and the durable JetStream layer.
- Google Pub/SubGoogle Pub/Sub is a global managed messaging service with a publish/subscribe model that scales automatically.
- Apache PulsarPulsar is a distributed messaging and streaming platform that separates brokers from storage and has built-in multi-tenancy.
Related topics
Sources
Logos belong to their owners and are used for identification only. Icons: Simple Icons (CC0), Devicon (MIT).