Message queue

BackendTier 3 · scale vocabularyPhase 4 · Take money

An orderly line for background work that holds tasks safely until a worker can handle them, even across crashes and spikes.

When one part of a system produces work faster than another can handle it, or a service is briefly down, work sent directly is lost or overwhelms the receiver. A message queue exists to hold work in line between producer and consumer, so each side runs at its own pace and nothing is dropped when load spikes.

When the backend hands off work, it drops a message into a queue. Workers pull from the queue and process tasks one by one. If a spike creates 10,000 emails at once, the queue holds them and workers work through the backlog rather than everything failing.

If a worker crashes mid-task, the message isn't lost; it goes back in the line to be retried. The queue is what makes background work reliable under load.

A junior PM, stuck

During the Eid sale a wave of customers got their order confirmations about 25 minutes late, and support escalated it to me as a possible outage. Eng closed it with "the queue backed up, it is not a bug," and I could not tell whether that means work was lost or just slow. I have to write the follow-up and say which.

The queue metrics settle this in about five minutes, and the answer is slow, not lost. A queue sits between the part that creates work and the workers that do it, and its depth is just how many messages are waiting in line. I pulled the notification queue's depth through the sale, from before the rush to fully drained, and trimmed it to the lines that tell the story.

Notification queue depth during the Eid sale
producers enqueue, workers drain, one line in between
19:00 enqueued/min 130 drained/min 120 depth 40 oldest 3s
19:05 enqueued/min 500 drained/min 120 depth 1900 oldest 40s
19:15 enqueued/min 500 drained/min 120 depth 5700 oldest 9m
19:22 enqueued/min 500 drained/min 120 depth 9040 oldest 22m
19:26 enqueued/min 260 drained/min 480 workers 3->12 depth 8100 oldest 21m
19:45 enqueued/min 150 drained/min 480 depth 300 oldest 40s
20:02 enqueued/min 140 drained/min 150 depth 20 oldest 2s

Click a step to see the lines it points at.

Reading a backlog as lost work and telling support the confirmations failed. In a queue they are delayed, not dropped; announcing an outage over late messages creates a second, self-inflicted problem.
Treating queue depth as the thing to fix. Depth is a symptom; the real levers are drain rate (more workers) or a lower arrival rate, not the queue in the middle.
Shipping a feature that fires a burst of tasks without asking if it is queued. Sent directly, a flood overwhelms the receiver under load; queued, the same flood waits in line and drains after.
Promising real-time delivery for queued work. A queue trades instant for reliable; if something truly must be instant, a background queue is the wrong place to put it.

Write the follow-up: "The notification queue held every confirmation during the sale. Arrivals hit 500 a minute against 120 draining, so depth climbed to about 9,000 and the oldest message waited 22 minutes, then it drained once we scaled workers from 3 to 12. Nothing was lost; they were late." You read a queue as an arrival-versus-drain race instead of an outage.

"There's a backlog in the queue" explains why receipts or notifications are delayed during a surge; capacity, not a bug.
Queues make bursty work survivable; if a feature fires a flood of tasks, ask whether it's queued.

"Notification queue backed up during the sale, they went out 20 minutes late."

Appears in Phase 4, Take money.