Queues
Letting one part of a system hand off work to be done later, without waiting around for it.
What is it?
Some tasks don't need to happen instantly while a user waits — sending a confirmation email, resizing an uploaded image, generating a report. If a server tried to do all of that immediately during the original request, users would wait far longer than necessary. Instead, systems often use a message queue: the server drops a description of the task into a queue and responds to the user right away, while separate worker processes pick up tasks from the queue and handle them in the background.
Explain like I'm 10
It's like dropping a form into an in-tray at an office instead of waiting at the counter until someone finishes processing it. You move on with your day; a clerk works through the tray in order, at their own pace.
Examples
Conceptual producer/consumer with a queue
// Server (producer) — respond fast, queue the slow work
app.post("/signup", async (req, res) => {
await createUser(req.body);
await queue.push({ type: "welcome-email", userId: req.body.id });
res.send("Signed up!"); // doesn't wait for the email to send
});
// Worker (consumer) — runs separately, processes queued jobs
queue.onMessage(async (job) => {
if (job.type === "welcome-email") {
await sendWelcomeEmail(job.userId);
}
});How it works
A producer (like a web server) adds messages describing work to the queue. One or more consumers (worker processes) continuously check the queue and process messages, often removing each one only after it's successfully handled — so if a worker crashes mid-task, the message isn't lost and can be retried.
Producer → [ queue: job1, job2, job3 ] → Consumer(s) process jobsWhy does it exist?
Queues decouple "accepting a request" from "doing the (possibly slow) work," which keeps user-facing responses fast, smooths out sudden spikes in traffic, and makes it easier to retry failed work without affecting the original request.
When to use it
Reach for a queue whenever a request triggers work that doesn't need to finish before responding to the user — sending an email, processing an upload, generating a report — especially work that's slow or occasionally fails and needs retrying.
When not to use it
Don't queue work the user is actively waiting to see the result of right now — that just adds an unnecessary hop and delay. A queue also adds real operational complexity (workers to run, failures to monitor), so it's not worth reaching for until you actually have slow or bursty background work to offload.
Common mistakes
Putting time-sensitive, user-facing work into a queue when the user actually needs to see the result immediately.
Not handling failures — a worker that crashes mid-task should allow the message to be retried, not silently lost.
Letting the queue grow unbounded without enough workers to keep up, causing delays to pile up.
Practice exercises
- Easy:
List three real tasks in a typical web app that are good candidates to run through a queue instead of immediately.
- Medium:
Explain, in your own words, why queues help a system handle sudden traffic spikes better.
- Hard:
Describe how you'd handle a job that fails repeatedly (e.g. a broken email address) so it doesn't get retried forever.
Interview questions
What problem do message queues solve?
They let a system hand off slow or non-urgent work to be processed later, keeping the original request fast and smoothing out traffic spikes.
What are 'producers' and 'consumers' in a queue system?
Producers add messages/jobs to the queue; consumers (workers) read and process those messages, usually independently and in parallel.
Why are queues useful for reliability, not just speed?
Because a message can be safely retried if a worker fails partway through, instead of the work being lost entirely.