Вы запускаете продакшн — и сервер падает под нагрузкой от отправки 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 с гарантией результата. Получите консультацию инженера прямо сейчас.







