Содержание
Коротко
Не каждая медленная операция должна блокировать HTTP-ответ: письма, webhooks, ресайз изображений, отчёты — классические фоновые задачи. На Dev.to разобрали Swig — очередь на Go с хранением jobs в PostgreSQL, без отдельного брокера сообщений.
Что произошло
Автор исходит из простой мысли: если Postgres уже крутится в проде, зачем поднимать Redis «только ради очереди»? Swig показывает, как уложить фоновую работу в ту же СУБД, опираясь на транзакции и блокировки строк.
Архитектура выглядит так. Есть таблица jobs с payload в JSONB, статусами, счётчиком попыток и метками времени. Воркеры на Go забирают задачу внутри транзакции — два процесса не должны взять одну и ту же строку. Рядом реестр воркеров и ведущий процесс для обслуживания: протухшие lease, повторные попытки, уборка старых записей.
Интерфейсы в Go описывают поведение обработчика; goroutines дают параллелизм; context — отмену и таймауты на выполнение. Чтобы не крутить бесконечный опрос БД, используют LISTEN/NOTIFY: после вставки job воркеры получают сигнал и просыпаются.
Пример домена в статье — надёжная обработка фоновых операций в веб-приложении, но паттерн переносится на любой сервис, где важны повторы и идемпотентность.
Почему это важно
Многие команды по умолчанию добавляют RabbitMQ или Redis, хотя нагрузка — десятки–сотни задач в секунду, а критичнее предсказуемость и один контур эксплуатации. Очередь на Postgres делит бэкапы, мониторинг и миграции с основным приложением.
Честное ограничение: при очень высоком QPS и жёстком SLA на задержку доставки специализированный брокер может выиграть. Для типичного веб-продукта схема «таблица + воркеры» живёт годами — особенно если команда уже умеет админить Postgres лучше, чем второй data store.
На практике
- Спроектируйте схему job:
id,kind,payload jsonb,status,attempts,run_at,locked_at,locked_by. - Забирайте задачу в транзакции с
FOR UPDATE SKIP LOCKED(или эквивалентом в вашей версии). - Делайте обработчики идемпотентными — повтор после сбоя не должен дважды отправить письмо или списать деньги.
- Шлите NOTIFY после
COMMITвставки; раз в N секунд оставьте резервный опрос на случай пропущенного сигнала. - Выделите ведущий процесс для requeue зависших jobs и архивации истории.
- Метрики: глубина очереди, возраст старейшей pending-задачи, доля failed.
Итог
Swig на Dev.to — хороший учебный каркас очереди на PostgreSQL в Go: блокировки, JSONB, NOTIFY, контексты. Если Postgres уже в стеке, имеет смысл оценить такой контур до покупки второго хранилища. Код и детали схемы — в оригинале.