All the parts

Build · Do it later

Queues and jobs

How do I do slow work without making the user wait?

What it is

A queue is a to-do list for your code. Your app drops a job on the list and answers the user right away. A separate worker program picks jobs up one by one and does the slow part, like sending email or resizing images.

It is a restaurant order slip: the waiter pins the slip up and walks away, and the kitchen cooks when it is ready.

Add it when Something takes more than a second or two, can fail and be retried, or talks to another company's API.

It can wait when Everything finishes instantly inside the request and nothing needs a retry.

1 Which one should I pick?

Answer what you can. The ranking updates as you go, and you can ignore it if you disagree.

Where does your app run?
What do you need most?
What matters most right now?

Most people start with

2 Side by side

Three pips is strong, one is weak. Pick a row to read about it below.

OptionQuick to set upCheap while smallEasy to leaveRoom to growPrice
Free tier, then pay per request
Free library; you pay for Redis and a server
Free tier, then pay per run
Free to self-host, or pay a hosting company
Free to self-host; managed versions are pay as you go

3 Look closer, then wire it in

Cloud primitive

AWS SQS

Amazon's plain, reliable queue. You send messages and workers read them.

Pick it when You already run on AWS and want a queue you never have to look after.

Skip it if You want a nice dashboard, scheduling and retries without wiring them up yourself.

  • Nothing to run or patch
  • Very reliable and scales on its own
  • Built-in dead-letter queue for failed jobs
  • AWS accounts and permissions are confusing at first
  • You write the worker loop yourself
Quick to set up
Cheap while small
Easy to leave
Room to grow

PriceFree tier, then pay per request

How to connect it

  1. Create a queue in the AWS console and note its URL.
  2. Create an access key that is only allowed to use that queue.
  3. Send a message from your app with the AWS SDK.
  4. Run a worker that reads messages, does the work, then deletes each message.
Put these in your .env file
  • AWS_REGION
  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY
  • SQS_QUEUE_URL
enqueue.ts
import { SQSClient, SendMessageCommand } from "@aws-sdk/client-sqs";

const sqs = new SQSClient({ region: process.env.AWS_REGION });

export const enqueue = (job: object) =>
  sqs.send(new SendMessageCommand({
    QueueUrl: process.env.SQS_QUEUE_URL,
    MessageBody: JSON.stringify(job),
  }));

4 Watch it work

Press play, or step through one message at a time.

Press Play to watch it run · 9 steps

The app answers fast and a worker does the slow part, with a retry if it fails.

Doing slow work laterThe app answers fast and a worker does the slow part, with a retry if it fails.Request: export my reportAdd job: export report 42Got it, we are working on itAny jobs for me?Job: export report 42Do the slow work (fails once)Failed: try again laterSame job again, second tryDone: remove the job
  • Client
  • Service
  • Queue
  • Worker
Text description
  1. Browser → Your app: Request: export my report
  2. Your app → Queue: Add job: export report 42
  3. Your app replies to Browser: Got it, we are working on it
  4. Worker → Queue: Any jobs for me?
  5. Queue replies to Worker: Job: export report 42
  6. Worker: Do the slow work (fails once)
  7. Worker → Queue: Failed: try again later
  8. Queue replies to Worker: Same job again, second try
  9. Worker → Queue: Done: remove the job

5 Mistakes to skip

  • Doing slow work inside the request.

    Put a job on a queue and reply right away. Tell the user it is in progress.

  • Writing jobs that are not safe to run twice.

    Queues can deliver a job more than once. Make jobs idempotent: check if the work is already done before doing it.

  • Ignoring jobs that keep failing.

    Send them to a dead-letter queue (a holding area for failed jobs) and set an alert so you notice.

See where it sits in a whole app

The stack builder draws your product with queues and jobs in it and animates a request through it.

Open the stack builder

Works closely with