Вы запускаете продакшн — и сервер падает под нагрузкой от отправки email? Или cron-задачи выполняются не в том порядке, отчёты уходят в пустоту? Синхронная обработка тормозит API, пользователи получают ошибки. Типичный сценарий: 10 000 писем в минуту — база данных блокируется, latency растёт до 30 секунд. BullMQ решает эти проблемы: асинхронная очередь на Redis с приоритетами, повторными попытками и мониторингом. В одном проекте на 50 000 пользователей после внедрения BullMQ нагрузка на сервер упала на 70%, а время ответа API — с 2 секунд до 200 мс. Наш опыт — более 10 лет и 50+ проектов с очередями. Правильно сконфигурированная очередь сокращает простои и устраняет потерю данных. Экономия в месяц составляет значительную сумму за счет снижения нагрузки на сервер и сокращения времени разработки.
Мы настроили BullMQ для десятков проектов — от стартапов до enterprise. В этой статье — проверенная конфигурация с нуля до production под ключ.
Установка
Установите пакеты: npm install bullmq ioredis. BullMQ требует Redis версии 6+. Убедитесь, что сервер доступен.
Конфигурация соединения
// lib/redis.ts
import { Redis } from 'ioredis';
export const redisConnection = new Redis({
host: process.env.REDIS_HOST || 'localhost',
port: Number(process.env.REDIS_PORT) || 6379,
password: process.env.REDIS_PASSWORD,
maxRetriesPerRequest: null,
enableReadyCheck: false,
});
maxRetriesPerRequest: null — критично для корректного переподключения. enableReadyCheck: false ускоряет старт.
Определение очередей
// queues/index.ts
import { Queue } from 'bullmq';
import { redisConnection } from '../lib/redis';
const defaultJobOptions = {
attempts: 3,
backoff: {
type: 'exponential' as const,
delay: 5000,
},
removeOnComplete: { count: 1000, age: 86400 },
removeOnFail: { count: 5000, age: 604800 },
};
export const emailQueue = new Queue('emails', {
connection: redisConnection,
defaultJobOptions,
});
// Для других типов задач создаются аналогичные очереди с теми же опциями.
Для разных типов задач используйте отдельные очереди — это улучшает мониторинг и производительность.
Воркеры
// workers/emailWorker.ts
import { Worker, Job } from 'bullmq';
import { redisConnection } from '../lib/redis';
import { sendEmail } from '../services/email';
interface EmailJobData {
to: string;
subject: string;
template: string;
variables: Record<string, unknown>;
}
const worker = new Worker<EmailJobData>(
'emails',
async (job: Job<EmailJobData>) => {
const { to, subject, template, variables } = job.data;
await job.updateProgress(10);
await sendEmail({ to, subject, template, variables });
await job.updateProgress(100);
return { sent: true, to, timestamp: new Date().toISOString() };
},
{
connection: redisConnection,
concurrency: 10,
limiter: {
max: 100,
duration: 60_000,
},
}
);
worker.on('completed', (job, result) => {
console.log(`Email sent to ${result.to}`);
});
worker.on('failed', (job, err) => {
console.error(`Email failed: job ${job?.id}:`, err.message);
});
worker.on('error', (err) => {
console.error('Worker error:', err);
});
export default worker;
Rate limiting — must-have для production. Без него вы рискуете заблокировать внешний API получателя.
Примеры добавления задач
Ниже — несколько сценариев: простая отправка, с задержкой, с приоритетом, массовая рассылка, cron-задачи и Flow.
// Простая задача
await emailQueue.add('welcome-email', {
to: user.email,
subject: 'Добро пожаловать!',
template: 'welcome',
variables: { name: user.name },
});
// С задержкой 5 минут
await emailQueue.add('follow-up-email', {
to: user.email,
subject: 'Как дела?',
template: 'follow-up',
variables: { name: user.name },
}, {
delay: 5 * 60 * 1000,
});
// С приоритетом (1 – высший)
await notificationQueue.add('push-notification', {
userId: user.id,
message: 'Срочное уведомление',
}, {
priority: 1,
});
// Массовая отправка
const jobs = users.map(user => ({
name: 'newsletter',
data: { to: user.email, template: 'newsletter' },
opts: { delay: Math.random() * 60_000 },
}));
await emailQueue.addBulk(jobs);
// Cron: ежедневный отчёт в 9:00 UTC
await reportQueue.add(
'daily-report',
{ type: 'daily', recipients: ['[email protected]'] },
{
repeat: { pattern: '0 9 * * *' },
jobId: 'daily-report-unique',
}
);
// Flow: ресайз → загрузка → уведомление
import { FlowProducer } from 'bullmq';
const flow = new FlowProducer({ connection: redisConnection });
await flow.add({
name: 'notify-user',
queueName: 'notifications',
data: { userId },
children: [{
name: 'upload-to-s3',
queueName: 'uploads',
data: { tempPath },
children: [{
name: 'resize-image',
queueName: 'images',
data: { originalPath, sizes: [200, 400, 800] },
}],
}],
});
Подробнее о cron-задачах
Для повторяющихся задач используйте опцию `repeat` с `pattern` (cron) или `every` (интервал). Уникальный `jobId` предотвращает дубликаты при повторных запусках.Bull Board (мониторинг)
Bull Board — веб-интерфейс для управления очередями. Интеграция с Express:
import { createBullBoard } from '@bull-board/api';
import { BullMQAdapter } from '@bull-board/api/bullMQAdapter';
import { ExpressAdapter } from '@bull-board/express';
import { emailQueue, notificationQueue, reportQueue } from './queues';
const serverAdapter = new ExpressAdapter();
serverAdapter.setBasePath('/admin/queues');
createBullBoard({
queues: [
new BullMQAdapter(emailQueue),
new BullMQAdapter(notificationQueue),
new BullMQAdapter(reportQueue),
],
serverAdapter,
});
app.use('/admin/queues', authenticate, serverAdapter.getRouter());
Bull Board даёт полный контроль: просмотр задач, повторный запуск, очистку. Мониторинг не нагружает Redis — запросы асинхронны. 80% задач выполняются с первой попытки, а задержка между повторными попытками увеличивается экспоненциально: 5, 10, 20 секунд.
Почему BullMQ лучше EventEmitter или RabbitMQ?
BullMQ быстрее в 3 раза для типовых веб-задач, чем RabbitMQ, и не требует покупки лицензии. В отличие от EventEmitter, данные сохраняются в Redis — при падении сервера задачи не теряются. BullMQ поддерживает exponential backoff и приоритеты, чего нет у EventEmitter. Сравнение:
| Особенность | BullMQ | RabbitMQ | EventEmitter |
|---|---|---|---|
| Персистентность | Да (через Redis) | Да | Нет |
| Приоритеты | Да | Нет | Нет |
| Exponential backoff | Да | Требует конфигурации | Нет |
| Мониторинг | Bull Board | Management UI | Нет |
| Лицензия | Open Source | Open Source (есть enterprise) | Бесплатно |
Как настроить мониторинг через Bull Board?
Bull Board — веб-интерфейс, который показывает все очереди, воркеры, статусы задач и ошибки. Интеграция с Express описана выше. Добавьте middleware — и вы получаете панель по адресу /admin/queues. Bull Board стабильно работает на проектах с 10+ очередями и 1000 задач в минуту. При необходимости подключаем аутентификацию и ролевую модель.
Как избежать потери данных при сбоях?
Используйте персистентность Redis — настройте save в redis.conf. В BullMQ задачи сохраняются до тех пор, пока не будут обработаны или не истечёт TTL. Параметр removeOnComplete с count: 1000 гарантирует, что в памяти остаётся только последние 1000 успешных задач — это экономит RAM. При падении Redis используйте AOF или репликацию. В наших проектах мы настраиваем Redis с appendonly yes и синхронизацией каждые 5 секунд.
Типичные ошибки при настройке очередей
- Забывают указать
maxRetriesPerRequest: null— соединение обрывается после первой ошибки. - Пропускают
enableReadyCheck: false— старт очереди затягивается на секунды. - Не настраивают лимиты — внешний API блокирует запросы (HTTP 429).
- Используют одну очередь для всех типов задач — усложняется мониторинг и отладка.
Что входит в настройку очередей под ключ
| Этап | Описание |
|---|---|
| Анализ | Оценка нагрузки, выбор стратегии (задержка, приоритет, повторные попытки) |
| Проектирование | Схема очередей, конфигурация Redis, настройка Rate Limiting |
| Реализация | Написание очередей, воркеров, Flow-цепочек |
| Мониторинг | Установка Bull Board, алерты в Telegram/Slack |
| Документация | README с архитектурой, инструкция по деплою |
| Поддержка | Гарантия настройки — 2 недели после сдачи |
Срок реализации
BullMQ для типового Node.js проекта (emails, уведомления, cron): 2–3 дня. С BullBoard, мониторингом и Flow: 3–4 дня. Оцените ваш проект бесплатно. Опыт более 10 лет и 50+ проектов гарантируют надёжность. Закажите профессиональную настройку BullMQ с гарантией результата. Получите консультацию инженера прямо сейчас.







