La tua app web invia email di conferma e il server si blocca per 10 secondi. Oppure durante l'import di un CSV con 50.000 righe, l'utente resta davanti a una schermata di caricamento che sembra infinita. Noi, di Meteora Web, lo vediamo spesso nei progetti che ci arrivano: processi sincroni che uccidono l'esperienza utente e consumano risorse. La soluzione? Spostare il lavoro pesante fuori dal ciclo di richiesta/risposta.
Una coda di job basata su Redis ti permette di fare esattamente questo: accettare una richiesta, metterla in coda, rispondere subito all'utente e processare il lavoro in background. Due degli strumenti più usati in produzione sono BullMQ (Node.js) e Sidekiq (Ruby). In questa guida vediamo come funzionano, quando usarli e come configurarli per non avere sorprese.
Perché usare Redis per le code di job?
Redis non è solo una cache. La sua natura in-memory, con strutture dati come liste e sorted set, lo rende ideale per implementare code persistenti e atomiche. Con i comandi LPUSH/BRPOP puoi creare una coda FIFO in tre righe. Ma in produzione servono: ritentativi, priorità, scheduling, rate limiting. Questa è la ragione per cui esistono librerie come BullMQ e Sidekiq: costruiscono sopra Redis astrazioni robuste per gestire fallimenti e coda in modo professionale.
Sponsored Protocol
Noi abbiamo scelto Redis per le code proprio perché è già spesso presente nello stack (grazie alla cache o alle sessioni). Zero infrastruttura extra. E come dico sempre: possedere il proprio stack batte affittarlo. Con Redis i tuoi dati sono sotto controllo.
Cosa cambia tra BullMQ e Sidekiq?
Domanda pratica: se il tuo backend è Node.js, BullMQ è la scelta naturale. Se usi Ruby on Rails, Sidekiq è lo standard de facto. Entrambi si appoggiano a Redis e offrono funzionalità simili: job persistenti, ritentativi, priorità, scheduling, job ricorrenti. Ma ci sono differenze che contano.
BullMQ (Node.js)
BullMQ è la versione moderna della libreria Bull. Scritto in TypeScript, sfrutta le Promise e i Worker. Permette di gestire code concorrenti, sandboxing dei job (esecuzione in processi separati), e ha un pannello di amministrazione open-source chiamato Arena. Noi lo usiamo nei progetti Laravel con Vue (usiamo Node per task asincroni) e funziona bene in cluster con Redis replicato.
Sidekiq (Ruby)
Sidekiq è maturo (dal 2012), estremamente performante, con un thread pool di default che processa job contemporaneamente. Ha un'interfaccia web integrata, plugin per scheduling come sidekiq-cron, e gestisce in modo nativo la connessione con Active Job di Rails. Il punto di attenzione è la concorrenza: Sidekiq è multi-thread, quindi il tuo codice Ruby deve essere thread-safe.
Sponsored Protocol
Come configurare una coda con BullMQ?
Vediamo un esempio reale. Supponiamo di dover generare un PDF dopo l'acquisto e inviarlo via email. Con BullMQ creiamo una coda e un worker.
// Installazione: npm install bullmq ioredis
const { Queue, Worker, QueueScheduler } = require('bullmq');
// Connessione Redis
const connection = { host: 'localhost', port: 6379 };
// Coda per i PDF
export const pdfQueue = new Queue('pdf-generation', { connection });
// Aggiungere un job
await pdfQueue.add('generate', {
orderId: 123,
userId: 456,
email: 'cliente@esempio.com'
}, {
attempts: 3,
backoff: { type: 'exponential', delay: 1000 },
removeOnComplete: { age: 3600 }
});
// Worker
const worker = new Worker('pdf-generation', async job => {
const { orderId, userId, email } = job.data;
// Simula generazione PDF (operazione lenta)
console.log(`Genero PDF per ordine ${orderId}`);
await generatePDF(orderId);
// Invia email
await sendEmail(email, 'Ecco il tuo PDF');
console.log('Job completato');
}, { connection, concurrency: 5 });
worker.on('completed', job => console.log(job.id, 'done'));
worker.on('failed', (job, err) => console.error(job.id, err));
// Scheduler per gestire job ritardati o ripetuti
new QueueScheduler('pdf-generation', { connection });
Con questo setup, se la generazione fallisce, BullMQ riprova con backoff esponenziale. I job sono persistenti su Redis fino al completamento o alla scadenza configurata. Noi aggiungiamo sempre removeOnComplete per non riempire la memoria.
Sponsored Protocol
Come implementare un worker con Sidekiq?
In Rails, il setup è ancora più snello. Usiamo Sidekiq con Redis e Active Job.
# Gemfile
gem 'sidekiq'
gem 'sidekiq-cron' # per scheduling
# config/initializers/sidekiq.rb
Sidekiq.configure_server do |config|
config.redis = { url: 'redis://localhost:6379/0' }
end
Sidekiq.configure_client do |config|
config.redis = { url: 'redis://localhost:6379/0' }
end
# app/workers/pdf_generator_worker.rb
class PdfGeneratorWorker
include Sidekiq::Worker
sidekiq_options retry: 3, backtrace: true
def perform(order_id, user_id, email)
generate_pdf(order_id)
send_email(email, 'Ecco il tuo PDF')
end
end
# Chiamata dal controller
PdfGeneratorWorker.perform_async(order.id, user.id, user.email)
Per eseguire Sidekiq in produzione: bundle exec sidekiq. La console web è accessibile montando Sidekiq::Web nelle rotte. Un consiglio dalla nostra esperienza: configurare concurrency in base ai core della macchina, e tenere d'occhio la latenza con sidekiq-monitor.
Sponsored Protocol
Come gestire errori e ritentativi nelle code Redis?
La gestione degli errori è cruciale. In BullMQ si definiscono attempts e backoff direttamente nel job. In Sidekiq si usa retry e opzioni come retry_count. Noi consigliamo sempre di loggare tutti i fallimenti e notificare il team. Un job fallito dopo 3 tentativi dovrebbe finire in una coda di dead letter (DLQ). BullMQ ha removeOnFail, Sidekiq ha DeadSet.
// BullMQ – gestione dead letter
worker.on('failed', async (job, err) => {
await deadLetterQueue.add('failed', job.data, {
attempts: 1,
backoff: { type: 'fixed', delay: 0 }
});
});
Come monitorare lo stato della coda Redis?
Serve un dashboard. Per BullMQ, Arena è open-source e leggero. Per Sidekiq, l'interfaccia web integrata è già completa. In produzione, aggiungiamo allarmi su metriche chiave: lunghezza della coda, job in ritardo, tasso di fallimenti. Con Redis possiamo esporre queste metriche a Prometheus via sidekiq-prometheus o bull-mq-prometheus.
Sponsored Protocol
Cosa fare adesso
- Identifica il carico asincrono nella tua app: email, generazione file, webhook, elaborazione dati. Spostalo in una coda Redis.
- Scegli la libreria giusta: BullMQ per Node.js, Sidekiq per Ruby. Se usi stack misti, entrambi possono convivere sullo stesso Redis con code separate.
- Configura retry con backoff e dead letter queue. Non lasciare job in pending per sempre.
- Monitora la coda con un dashboard e metriche di alert. Redis può diventare un collo di bottiglia se non dimensionato.
- Testa in staging la concorrenza e il comportamento in caso di crash del worker. Redis persistente (AOF + RDB) evita perdite.
Se vuoi approfondire l'ecosistema Redis, leggi la nostra guida pillar su Redis e caching strategies. Per domande pratiche su BullMQ o Sidekiq, scrivici.