DevPath · Learn to code ESPTEN

Real time, GraphQL and messaging

Message queues and background jobs

Slow tasks in the request-response cycle

Imagine that when a user signs up you want to send them a welcome email. Sending the email takes 2 seconds. If you do it inside the handler, the user waits those 2 seconds for the page to load. Even worse: processing a video or generating a report can take minutes.

The rule: take slow tasks out of the request-response cycle. Respond quickly to the user and do the heavy work in the background.

Message queues

A message queue decouples whoever requests the work from whoever does it:

// Producer: enqueue and respond right away
await queue.add("sendEmail", { to: "ana@mail.com" });
res.status(202).json({ status: "in progress" });

// Consumer (worker): processes in the background
worker.process("sendEmail", async (job) => {
  await sendEmail(job.data.to);
});

Retries

If a job fails (the email API does not respond), the queue can retry automatically a few times before sending it to a dead-letter queue for manual review. This gives resilience against transient failures.

Idempotency

If a job is retried, it might run more than once. An operation is idempotent when running it N times produces the same effect as running it once. "Set the balance to 100€" is idempotent; "add 100€" is not (it would be duplicated on each retry).

The usual technique: give each job a unique id and record the ones already processed, so that a retry of the same id does not apply the effect again.

Put this into practice

DevPath is a hands-on course: you read the theory here; in the app you put it into practice with exercises that really run, offline.

Start free in the app →
← GraphQL: one schema, one endpointView the module →