Many producers, one queue, workers competing for each message
Each message goes to exactly one worker. Add Worker D at the peak, and no producer notices.
The life of a message
- Send: stored durably before the “ok”
- Receive: hidden from others under a lease
- Process, then ack: only now is it deleted
- Crash: the lease expires and it comes back
A worker charges the card, then crashes before deleting the message.
The catch
The queue can’t tell that from a crash before the charge, so it redelivers. Handlers must be safe to run twice.
Longer lease, safer?
Bad: A 15-minute visibility timeout
A crashed job then idles almost 15 minutes before anyone retries it.
Good: A few times p99, plus heartbeats
Long jobs extend their lease with ChangeMessageVisibility as they go.
A queue deletes on ack. A log keeps records and tracks offsets.
Need replay, or several readers of every message? Use a log like Kafka. Need unlimited workers on one stream of jobs? A queue.
8×
the workers, when one dependency slows
Little’s law: 1,200 a second × 0.25 s = 300 in progress. At 2 s per message it’s 2,400, though traffic never changed.
When not to put a queue in the way
- The caller needs the answer now
- The user must read their own write
- Every consumer needs every message, so pub/sub
- Average arrivals exceed capacity, so shed load
Remember
A queue trades immediacy for resilience. Expect duplicates, size workers with Little’s law, and alarm on the oldest message’s age.