Содержание
Коротко
Приложение для конвертации и шаринга файлов сначала делало всю работу внутри HTTP-запроса. С ростом размеров файлов пользователи ждали сотни миллисекунд там, где ответ мог прийти сразу. Автор вынес тяжёлую обработку в BullMQ и Redis — и получил измеримый выигрыш по задержке и пропускной способности.
Что произошло
Первая версия была простой: загрузка → конвертация в том же процессе, что обрабатывает API → ответ с результатом. На маленьких файлах это работало. Когда объёмы выросли, соединение держалось открытым, пока сервер занят CPU и диском — хотя клиенту в этот момент нужен был лишь факт «принято в работу».
Новый поток: загрузка → задача в BullMQ → мгновенный ответ API → воркер конвертирует → обновление статуса → пользователь получает файл. Redis хранит очередь; воркеры масштабируются по параллелизму; повторы и обработка сбоев встроены в модель очереди.
Автор прогнал нагрузочный тест с 20 параллельными запросами. p95 задержки API упал примерно в 212 раз (с 800 мс до 3,8 мс). Пропускная способность выросла в 4,8 раза (с 1,3 до 6,2 запросов в секунду). Ускорилась не сама конвертация — изменилась архитектура: тяжёлая работа ушла с критического пути запроса.
Почему это важно
Синхронная обработка в API кажется проще, пока нагрузка низкая. Но любой долгий I/O или CPU в обработчике запроса бьёт по таймаутам, пулу соединений и UX. Паттерн «принять быстро, обработать отдельно» — базовый для файлов, видео, отчётов, рассылок.
Цена асинхронности честная: нужны Redis, процессы-воркеры, мониторинг очереди и отложенная согласованность — пользователь не получает файл в том же ответе, что загрузку. Если бизнес требует мгновенного результата в одном HTTP-цикле, синхронный путь может остаться оправданным. Для конвертации и шаринга это редко так.
На практике
- Отделите приём файла от тяжёлой обработки — API возвращает
jobIdи статус. - Выберите очередь с повторами и очередью «мёртвых» задач (BullMQ на Redis — распространённый вариант в Node.js).
- Масштабируйте воркеры, а не только реплики API — задачи, нагружающие CPU, живут там.
- Отдавайте клиенту опрос статуса, webhook или SSE для состояния «готово».
- Замеряйте p95/p99 API отдельно от времени полной обработки задачи.
- Документируйте компромисс: проще код vs инфраструктура и задержка до результата.
Итог
История на Dev.to — короткое, но цифрами подкреплённое напоминание: часто выигрыш даёт не «ускорение функции», а вынос работы из HTTP-запроса. BullMQ + Redis окупились для файлового сервиса; ваш порог может быть другим, но принцип универсален.