Serverless-очередь задач: уберите флот воркеров с Redis
BullMQ нужны Redis, воркер-процесс и стратегия ретраев. SQS нужны IAM, Lambda-консьюмер и настройка dead-letter-очереди. Пайплайны Inquir дают семантику продюсер/консьюмер — поставить задачу, выполнить её в изолированном контейнере, повторить упавшие шаги — без развёртывания и эксплуатации инфраструктуры очередей.
Обновлено: 2026-06-28
Кратко
Суть ответа
Serverless-очередь задач: уберите флот воркеров с Redis. Inquir — не высокопроизводительный брокер сообщений со строгим порядком, но эксплуатировать такой брокер вам и не нужно. Пайплайны плюс очередь durable-задач (ретраи на Postgres, экспоненциальный backoff и dead-letter-очередь) снимают операционную нагрузку очереди — политика ретраев на шаг, история прогонов по шагам и выполнение в изолированных контейнерах, — так что вы пишете логику задач, а не инфраструктуру очереди.
Когда подходит
- Нужны постановка в очередь, ретраи и история прогонов без эксплуатации Redis, SQS или флота воркеров
- Фоновые задачи должны делить секреты и наблюдаемость с вашим HTTP API
На что обратить внимание
- Очередь в памяти API-процесса теряет задачи при рестарте и не масштабируется горизонтально без дублей доставки. Воркер-процесс — самый хрупкий компонент: он должен постоянно работать, дорабатывать при деплое и переживать падения без потери задач в работе.
- Вызов SQS из каждого обработчика размазывает IAM-учётки, логику ретраев и управление ключами идемпотентности по всей кодовой базе. Каждый новый тип задачи воспроизводит тот же шаблонный код.
Нагрузка и где ломается
Во что обходится продакшен-очередь задач
- Бэкенд очереди: Redis, SQS или RabbitMQ — развёрнутый, под мониторингом и на критическом пути каждой задачи
- Флот воркеров: постоянные процессы, которые читают очередь, масштабируются под нагрузку и безопасно дорабатывают при деплое
- Политика ретраев и backoff: экспоненциальная задержка, лимит попыток и ручной разбор задач, исчерпавших ретраи
- Наблюдаемость: отдельный дашборд для глубины очереди, зависших задач и причин сбоев
Очереди задач решают реальные проблемы: отделяют продюсеров от консьюмеров, сглаживают всплески трафика, повторяют нестабильную работу. Но сама очередь становится инфраструктурой, которую вы эксплуатируете ещё до первой бизнес-задачи.
Компромиссы
Почему самодельные очереди добавляют операционный долг
Очередь в памяти API-процесса теряет задачи при рестарте и не масштабируется горизонтально без дублей доставки. Воркер-процесс — самый хрупкий компонент: он должен постоянно работать, дорабатывать при деплое и переживать падения без потери задач в работе.
Вызов SQS из каждого обработчика размазывает IAM-учётки, логику ретраев и управление ключами идемпотентности по всей кодовой базе. Каждый новый тип задачи воспроизводит тот же шаблонный код.
Как помогает Inquir
Пайплайны как продюсер/консьюмер без эксплуатации очереди
Inquir — не высокопроизводительный брокер сообщений со строгим порядком, но эксплуатировать такой брокер вам и не нужно. Пайплайны плюс очередь durable-задач (ретраи на Postgres, экспоненциальный backoff и dead-letter-очередь) снимают операционную нагрузку очереди — политика ретраев на шаг, история прогонов по шагам и выполнение в изолированных контейнерах, — так что вы пишете логику задач, а не инфраструктуру очереди.
Продюсер вызывает global.durable.startNew(jobName, undefined, payload) из любой функции. Консьюмер — обработчик шага пайплайна, который запускает управляемый пул воркеров (10 параллельно на функцию, 50 глобально, глубина внутренней очереди 100). Ни строки подключения к Redis, ни systemd-юнита воркера, ни скрипта дорабатывания очереди при деплое.
Сравнение
Сравнение эксплуатации очередей
Что вы разворачиваете и эксплуатируете при каждом подходе — сравнение не возможностей, а эксплуатации.
| Зона ответственности | BullMQ + Redis | AWS SQS + Lambda | Пайплайны Inquir |
|---|---|---|---|
| Инфраструктура очереди | Кластер Redis (разворачиваете вы) | Очередь SQS (управляет AWS) | Нет — встроена в пайплайн |
| Воркер-процесс | Воркеры BullMQ (запускаете вы) | Lambda-консьюмер (настраиваете вы) | Шаги пайплайна (запускает платформа) |
| Настройка ретраев | На задачу в коде воркера | Redrive policy + DLQ | На шаг в конфигурации пайплайна |
| История прогонов / наблюдаемость | Ключи Redis (короткий TTL) | CloudWatch + разбор DLQ | Записи выполнения (хранятся 30 дней) |
| Модель секретов | Отдельно от HTTP-маршрутов | IAM + Secrets Manager | Общие секреты воркспейса |
| Гарантия доставки | At-least-once через Redis | At-least-once через SQS | At-least-once (без гарантии порядка) |
Что вы получаете
Паттерны очереди задач на Inquir
Постановка из любого продюсера
HTTP 202, проверенный вебхук, cron-расписание или шаг другого пайплайна — один вызов постановки (global.durable.startNew) независимо от точки входа.
Ретраи на шаг с backoff
Настройте число попыток и задержку на каждый шаг пайплайна. Упавшие шаги повторяются без перезапуска уже завершённых — аналог опций ретраев задачи, но без отдельной очереди ретраев.
История прогона как запись выполнения
Каждая постановка создаёт запись прогона: входной payload, выходы шагов, длительность, число ретраев и причина сбоя. Всё видно в консоли без запросов к Redis и проверки глубины DLQ.
Fan-out без второй очереди
Один шаг задачи вызывает global.durable.startNew() N раз и порождает параллельные дочерние пайплайны. Ни отдельного продукта-очереди, ни настройки fan-out по топикам.
Что дальше
Как заменить BullMQ или SQS пайплайнами Inquir
Написать обработчик консьюмера
Экспортируйте функцию, которая читает event.payload и возвращает структурированный выход, — сторона консьюмера. Сделайте её идемпотентной: проверяйте ключ дедупликации до записи побочных эффектов.
Ставить в очередь из продюсера
Замените вызов queue.add() или sqs.sendMessage() на global.durable.startNew(jobName, undefined, payload) и сразу возвращайте ответ.
Настроить ретраи и мониторинг
Задайте число попыток и backoff в конфигурации шага пайплайна. Следите за зависшими прогонами в истории выполнения; оповещайте при превышении порога доли сбоев.
Пример кода
Продюсер → консьюмер без Redis и SQS
Продюсер валидирует вход и ставит задачу одним вызовом. Обработчик консьюмера работает в изолированном контейнере с ретраями на стороне платформы.
export async function handler(event) { const { exportId, format } = JSON.parse(event.body || '{}'); if (!exportId) return { statusCode: 400, body: JSON.stringify({ error: 'exportId required' }) }; // Replace: queue.add('run-export', { exportId, format }) const { instanceId: jobId } = await global.durable.startNew('run-export', undefined, { exportId, format: format ?? 'csv' }); return { statusCode: 202, body: JSON.stringify({ jobId, status: 'queued' }) }; }
export async function handler(event) { const { exportId, format } = event.payload ?? {}; // Idempotency: skip if already exported const existing = await db.findExport(exportId); if (existing) return { exportId, fileUrl: existing.url, skipped: true }; const rows = await fetchExportRows(exportId); const fileUrl = await writeExport(rows, format); await db.saveExport(exportId, fileUrl); await notifyExportReady(exportId, fileUrl); return { exportId, fileUrl, rowCount: rows.length }; }
Когда подходит
Когда пайплайны Inquir заменяют очередь задач
Когда это уместно
- Нужны постановка в очередь, ретраи и история прогонов без эксплуатации Redis, SQS или флота воркеров
- Фоновые задачи должны делить секреты и наблюдаемость с вашим HTTP API
Когда лучше выбрать другое
- Субмиллисекундная задержка очереди со строгим FIFO на миллионах задач в секунду — для такой пропускной способности и гарантий порядка нужен выделенный брокер сообщений
Частые вопросы
Частые вопросы
Гарантирует ли Inquir доставку exactly-once?
Нет. Вызовы пайплайнов выполняются at-least-once. Делайте обработчики консьюмера идемпотентными: проверяйте ключ дедупликации (например, exportId, jobId) до записи побочных эффектов, чтобы ретраи были безопасны.
Есть ли dead-letter-очередь?
Да. Очередь durable-задач отправляет задачу в dead-letter после исчерпания попыток и сохраняет последнюю ошибку, чтобы вы могли разобрать и переиграть проблемные сообщения, а не потерять их. Сбои шагов пайплайна дополнительно хранятся в истории выполнения для ручного replay из сохранённого payload.
Можно ставить задачи из обработчиков на Python или Go?
global.durable.startNew() — метод Node.js SDK. Из Python или Go отправьте POST на URL триггера пайплайна с тем же payload — API триггера доступен по HTTP из любого рантайма.
Чем это отличается от BullMQ?
BullMQ выполняет задачи в воркер-процессах, читающих очередь Redis: вы эксплуатируете Redis, масштабируете воркеры и разбираете DLQ. Шаги пайплайна Inquir работают в изолированных контейнерах под управлением платформы. Вы пишете обработчик консьюмера; планирование, ретраи и записи прогонов берёт на себя платформа.