Mensageria com BullMQ e Redis: Processamento Assíncrono que Funciona
Um endpoint que envia email, gera PDF e notifica um webhook externo leva 4 segundos para responder. O usuário espera. O load balancer faz timeout. O retry do cliente duplica a operação. Tudo isso porque o processamento acontece de forma síncrona dentro do ciclo de request/response.
BullMQ resolve esse problema com uma abstração de filas sobre Redis que é simples de operar e previsível de debugar. Diferente de soluções como RabbitMQ ou Amazon SQS, BullMQ roda no mesmo ecossistema Node.js, usa Redis como único backing store e oferece retry, prioridade, rate limiting e dead letter queue sem infraestrutura adicional.
Por que BullMQ e não as alternativas
A escolha de mensageria depende de três variáveis: volume de mensagens, complexidade de roteamento e quanto de infraestrutura você quer gerenciar.
| Critério | BullMQ + Redis | RabbitMQ (AMQP) | Amazon SQS | Kafka |
|---|---|---|---|---|
| Protocolo | Redis commands | AMQP 0-9-1 | HTTP/SQS API | Kafka protocol |
| Ordering garantido | Por fila (FIFO) | Por fila | FIFO opcional (custo extra) | Por partição |
| Retry nativo | Sim, com backoff configurável | Sim, com dead letter exchange | Sim, com redrive policy | Não nativo (consumer controla) |
| Rate limiting | Nativo por fila | Plugin | Não nativo | Não nativo |
| Infra necessária | Redis (que você já tem) | Broker dedicado | Conta AWS | Cluster Kafka + ZooKeeper |
| Caso ideal | Jobs assíncronos em aplicações Node.js com até ~50k jobs/min | Roteamento complexo entre serviços heterogêneos | Serverless ou integração AWS nativa | Streaming de eventos com replay |
Se sua aplicação é Node.js, já usa Redis para cache ou sessão, e o volume fica abaixo de 50 mil jobs por minuto: BullMQ é a escolha direta. Acima disso, ou com necessidade de replay de eventos, Kafka entra na conversa. Para roteamento fan-out complexo entre serviços em linguagens diferentes, RabbitMQ faz mais sentido.
Setup: Redis, BullMQ e a primeira fila
Instale as dependências. BullMQ precisa de Redis 5.0+ (usa Streams internamente) e Node.js 18+.
npm install bullmq ioredis
npm install -D @types/node typescript
A conexão com Redis deve ser centralizada. Não crie múltiplas instâncias de IORedis espalhadas pelo código.
// src/lib/redis-connection.ts
import IORedis from "ioredis";
// maxRetriesPerRequest: null é obrigatório para BullMQ.
// O default do ioredis é 20, e BullMQ usa blocking commands (BRPOPLPUSH)
// que não devem ter limite de retry por request.
export const redisConnection = new IORedis(
process.env.REDIS_URL || "redis://localhost:6379",
{
maxRetriesPerRequest: null,
enableReadyCheck: false,
}
);
Agora, a primeira fila. O padrão que funciona é separar a definição da fila (producer) do worker (consumer) em módulos distintos. Isso permite escalar workers independentemente do servidor HTTP.
// src/queues/email.queue.ts
import { Queue } from "bullmq";
import { redisConnection } from "../lib/redis-connection";
export interface EmailJobData {
to: string;
subject: string;
templateId: string;
variables: Record<string, string>;
}
export const emailQueue = new Queue<EmailJobData>("email", {
connection: redisConnection,
defaultJobOptions: {
attempts: 3,
// Backoff exponencial: 1s, 2s, 4s entre tentativas.
// Evita sobrecarregar o serviço de email durante instabilidade.
backoff: {
type: "exponential",
delay: 1000,
},
// Remove jobs completos após 24h para não inflar a memória do Redis.
removeOnComplete: { age: 86400 },
// Mantém jobs falhados por 7 dias para análise.
removeOnFail: { age: 604800 },
},
});
Workers: onde o processamento acontece
O worker é um processo separado. Pode rodar no mesmo servidor ou em máquinas dedicadas. BullMQ garante que cada job é processado por exatamente um worker (at-least-once delivery com locking via Redis).
// src/workers/email.worker.ts
import { Worker, Job } from "bullmq";
import { redisConnecti
---
Leia o artigo completo em [https://www.vivodecodigo.com.br/backend/mensageria-bullmq-redis-processamento-assincrono-nodejs](https://www.vivodecodigo.com.br/backend/mensageria-bullmq-redis-processamento-assincrono-nodejs)