TZ~/tizianozonta/blog
← torna al blog
Node04 maggio 2026 · 6 min

Queue e job con Node: lezioni da cinque anni di produzione

Retry, idempotenza e osservabilità: gli errori che pago ancora oggi.

Le code sono facili da avviare e difficili da gestire bene. Dopo cinque anni con BullMQ in produzione, questi sono i principi che non negozio più.

L’idempotenza non è opzionale

Un job può girare due volte. Sempre. Progetto ogni handler perché rieseguirlo sia innocuo.

jobs/invia-email.ts
import { Worker } from "bullmq";
new Worker("email", async (job) => {
const { userId, templateId } = job.data;
// Chiave di idempotenza: se già inviata, esco senza rifare nulla
const key = `sent:${userId}:${templateId}`;
if (await redis.get(key)) return;
await mailer.send(userId, templateId);
await redis.set(key, "1", "EX", 86_400);
});

Retry con backoff esponenziale

Fallire va bene, ritentare subito no: sovraccarica il sistema già in difficoltà.

queue.ts
await queue.add("email", payload, {
attempts: 5,
backoff: { type: "exponential", delay: 2_000 },
removeOnComplete: 1_000,
});

Osservabilità prima di tutto

Il consiglio che darei a me stesso di cinque anni fa:

Terminal window
# Un job che fallisce in silenzio è un incidente che scopri dal cliente
npm run queue:metrics -- --queue email --window 1h

Metti le metriche di coda (job attivi, falliti, latenza) su una dashboard prima di andare in produzione, non dopo il primo disastro.

← torna al blog