ATLAS CEO
🏗️Стройка 7 февраля 2026 г.

Trigger.dev в продакшене: как запускать фоновые задачи без боли

Станислав Виниченко · 5 мин чтения
Поделиться
Фоновые задачи и надежная оркестрация в продакшене

Фоновые задачи — это место, где AI-конвейер ломается первым

Вы написали промпт. Модель ответила. Парсер вытащил JSON. Контент красивый. Работает? Работает. На вашей машине. Один раз. С первого запуска.

А теперь запустите это 50 раз в сутки. С расписанием. С внешними API, которые возвращают 429 каждый третий запрос. С моделью, которая иногда отвечает за 2 секунды, а иногда за 45. С Replicate, у которого cold start может занять минуту. С GitHub API, который имеет rate limit 5,000 запросов в час. С Vercel deploy hook, который иногда просто не отвечает.

Это не edge-case. Это нормальный режим работы любого AI-пайплайна в продакшене. И если у вас нет инфраструктуры, которая умеет с этим жить — вы будете чинить руками. Каждый день. В выходные. В три часа ночи.

Content Factory на atlasceo.ru генерирует и публикует 5-10 статей в сутки. Полный цикл: планирование тем, генерация текста, создание иллюстраций через FAL.ai, сборка MDX, коммит в GitHub, деплой на Vercel. Всё — через Trigger.dev. И вот подробный разбор: почему, как, что сломалось и что работает.

99.4%
успешность задач за 30 дней
📊
~2,100
выполненных задач в месяц
🛡️
0
потерянных публикаций
⏱️
< 3 мин
среднее время обнаружения ошибки
Фоновые задачи и надежная оркестрация в продакшене
Генерация: FAL.ai FLUX Schnell
#1
🕰️

Эволюция фоновых задач

От cron до managed infrastructure: 20 лет поиска правильного ответа

Прежде чем говорить о Trigger.dev — контекст. Фоновые задачи — это не новая проблема. Индустрия решает её 20 лет, и каждое поколение инструментов фиксило баги предыдущего, добавляя свои.

2005

Cron + bash-скрипты. Расписание есть, retry нет, observability нет. Задача упала — узнаёшь утром из пустой базы. Или не узнаёшь. Для бэкапов и ротации логов — нормально. Для бизнес-логики — самоубийство.

2010

Celery (Python) / Sidekiq (Ruby). Очереди на Redis/RabbitMQ. Retry есть. Мониторинг — Flower/Sidekiq Web. Но: свой Redis, свой воркер-процесс, свой деплой. Инфраструктура разрастается быстрее кода.

2016

Bull / BullMQ (Node.js). Redis-очереди для JavaScript-мира. Хороший API, delayed jobs, rate limiting. Но всё ещё self-hosted: Redis нужно поддерживать, масштабировать, мониторить. Падение Redis = падение всего.

2020

Temporal / Inngest. Durable execution — задачи переживают перезагрузку сервера. Temporal мощный, но порог входа как у Kubernetes: месяц на настройку, прежде чем запустишь первый workflow. Inngest проще, но vendor lock.

2024

Trigger.dev v3. TypeScript-native. Задачи — это функции. Deploy одной командой. Dashboard с real-time логами. Retry, timeout, concurrency — декларативно. Serverless execution. Порог входа: 15 минут до первой задачи в проде.

Видите эволюцию? От «запусти скрипт и молись» до «опиши задачу как функцию, а инфраструктура сама разберётся». Trigger.dev — не революция. Это логичный итог 20 лет проб и ошибок.

"

Лучшая инфраструктура — та, о которой ты не думаешь. Trigger.dev не делает фоновые задачи «интересными». Он делает их скучными. А скучные задачи — это те, которые работают.

Стас, основатель Atlas CEO
#2
🏗️

Архитектура

Cron → Task → AI → Publish: как устроен конвейер Content Factory

Content Factory — это не один скрипт. Это цепочка задач, где каждое звено зависит от предыдущего, но может быть перезапущено независимо. Вот архитектура:

Schedule (cron 05:00 UTC)
  → cf4-atlas-website-daily-plan     // планирование тем на день
    → cf4-generate-article           // генерация текста (Claude/GPT-4o)
      → cf4-generate-images          // иллюстрации (FAL.ai FLUX Schnell)
        → cf4-assemble-mdx           // сборка MDX с компонентами
          → cf4-publish-github       // коммит в репозиторий
            → cf4-deploy-vercel      // триггер Vercel build

Каждая стрелка — это отдельная Trigger.dev задача. Каждая задача имеет свой retry policy, свой timeout, свой concurrency limit. Падение на любом этапе не убивает весь конвейер — задача ретраится, а downstream-задачи ждут.

Пайплайн задач от cron до публикации
Генерация: FAL.ai FLUX Schnell
// Пример: задача генерации статьи с retry и timeout
export const generateArticle = task({
  id: "cf4-generate-article",
  retry: {
    maxAttempts: 3,
    factor: 2,
    minTimeoutInMs: 5_000,
    maxTimeoutInMs: 60_000,
  },
  run: async (payload: { topic: string; persona: string }) => {
    const article = await generateWithClaude(payload);

    // Идемпотентность: проверяем, не опубликована ли уже
    const existing = await supabase
      .from("articles")
      .select("id")
      .eq("slug", article.slug)
      .single();

    if (existing.data) {
      logger.info("Article already exists, skipping", { slug: article.slug });
      return { status: "skipped", slug: article.slug };
    }

    await supabase.from("articles").insert(article);
    return { status: "created", slug: article.slug };
  },
});
🔑

Принцип независимых звеньев

Каждая задача в цепочке — самостоятельная единица. Можно запустить cf4-generate-images отдельно, передав slug. Можно перезапустить cf4-publish-github, не перегенерируя статью. Это не монолит — это конвейер с точками входа на каждом этапе.

#3
🧱

Три паттерна продакшена

Идемпотентность, retry, observability — без них пайплайн мёртв

Можно написать задачу за 10 минут. Можно даже задеплоить. Но без трёх паттернов она сломается в первую же неделю. Не «может сломаться». Сломается. Гарантированно.

♻️

Идемпотентность

Повторный запуск задачи не должен создавать дубликаты. Не должен публиковать статью дважды. Не должен списывать деньги за генерацию повторно. Каждая задача перед выполнением проверяет: а не сделано ли уже? Ключ дедупликации — slug статьи, content_hash, или уникальный ID задачи. Без этого один сбой сети → два поста в Telegram, два деплоя на Vercel, два списания с OpenAI.

Retry с exponential backoff

OpenAI возвращает 429? FAL.ai отвечает 503? GitHub API даёт timeout? Не паникуйте — ретрайте. Но не сразу: первый retry через 5 секунд, второй через 10, третий через 20. Exponential backoff — это уважение к API, который просит подождать. Без backoff вы получите бан вместо результата. В Trigger.dev это три строки конфига.

🧾

Structured logging

console.log('error happened') — это не логирование. Это крик в пустоту. Structured logging = JSON-события с контекстом: какой slug, какой этап, какой HTTP-код, сколько миллисекунд ушло. Trigger.dev logger пишет в dashboard, где можно фильтровать по run ID, по задаче, по статусу. Проблема найдена за минуту, а не за час.

Timeout на каждом уровне

Задача без timeout — это задача, которая может висеть вечно. Claude иногда думает 90 секунд. FAL.ai иногда думает 120. Если вы не ставите лимит — задача повисла, воркер занят, очередь растёт, новые задачи ждут. Мы ставим 120 секунд на генерацию текста, 180 на изображения, 60 на GitHub API. Если не уложились — retry.

💀

Dead letter queue

Задача упала 3 раза подряд? Не ретрайте бесконечно. Отправьте в dead letter: запишите в Supabase с статусом 'failed', отправьте алерт в Telegram. Утром разберётесь — с полным контекстом ошибки, а не с загадочным пустым слотом в расписании.

🔄

Graceful degradation

FAL.ai не работает? Не роняйте всю статью. Опубликуйте без иллюстраций, поставьте placeholder, создайте отложенную задачу на генерацию изображений. Лучше статья без картинки, чем ноль статей. Degradation — это не баг. Это стратегия.

Наблюдаемость: логи, трассировки, метрики
Генерация: FAL.ai FLUX Schnell
// Structured logging в Trigger.dev
import { logger } from "@trigger.dev/sdk/v3";

logger.info("Article generation started", {
  slug: payload.slug,
  persona: payload.persona,
  model: "claude-sonnet-4-20250514",
});

// После завершения
logger.info("Article generation completed", {
  slug: payload.slug,
  tokensUsed: result.usage.total_tokens,
  durationMs: Date.now() - startTime,
  wordCount: result.content.split(" ").length,
});
📊

Метрики retry за 30 дней

Из 2,100 задач: 1,970 выполнились с первой попытки (93.8%). 98 потребовали 1 retry (4.7%). 24 потребовали 2 retry (1.1%). 8 ушли в dead letter (0.4%). Ни одна публикация не потеряна. Retry — это не костыль. Это страховка, которая работает.

📬 Строите AI-конвейер или агентную систему? Подписывайтесь — разбираем паттерны продакшена без воды и маркетинга.

Подписаться в TG →
#4
⚖️

Скрипты на коленке vs. Trigger.dev

Честное сравнение: что вы теряете без нормальной оркестрации

Я знаю, о чём вы думаете. «У меня cron + node-скрипт на VPS, и всё работает». Работает — пока работает. Вот что происходит, когда масштаб растёт с 5 задач в день до 50.

Скрипты на коленке (cron + VPS)

Retry Ручной или никакой. Упало — перезапускаете ssh-сессию
Observability tail -f /var/log/app.log. Удачи найти ошибку вчерашнюю
Concurrency Надеетесь, что два cron-а не запустятся одновременно
Deploy scp + pm2 restart. Или docker-compose up -d и молитва
Масштабирование Купить VPS побольше. Потом ещё побольше
Стоимость отказа Молчаливый сбой. Узнаёте через часы или дни
Итого Работает на 5 задач/день. Ломается на 50.

Trigger.dev production contour

Retry Декларативный: maxAttempts, backoff, factor — в конфиге задачи
Observability Dashboard с real-time логами, фильтрами, timeline каждого run
Concurrency concurrencyLimit в конфиге. Очередь управляется автоматически
Deploy npx trigger.dev deploy. Одна команда. Zero-downtime.
Масштабирование Serverless: платите за выполнение, не за простой
Стоимость отказа Алерт в Telegram за < 3 минуты. Полный контекст ошибки
Итого Работает на 5 задач/день. Работает на 500.
Разница не в удобстве. Разница в том, спите ли вы спокойно. С cron на VPS — нет. С Trigger.dev — да.
"

Я потратил два года на cron + pm2 + ручной мониторинг. Переход на Trigger.dev занял две недели. Экономия нервов за первый месяц окупила всё. Время, потраченное на инфраструктуру — это время, не потраченное на продукт.

Стас, основатель Atlas CEO
#5
🔧

Сборка production-контура

7 шагов от нуля до полностью работающего пайплайна

Хватит теории. Вот конкретные шаги, которые мы прошли при миграции Content Factory на Trigger.dev. Каждый шаг — с кодом, граблями и решениями.

📦

Инициализация проекта

npx trigger.dev@latest init в корне проекта. Создаётся trigger.config.ts с базовой конфигурацией. Указываете projectRef из dashboard, папку с задачами (src/triggers/), runtime (node). Одна команда — и скелет готов. Не пишите конфиг руками — CLI сгенерирует правильный.

🏥

Первая задача — health check

Не начинайте с бизнес-логики. Напишите задачу, которая логирует 'hello world' и возвращает timestamp. Задеплойте. Убедитесь, что dashboard показывает run. Убедитесь, что логи читаемы. Только после этого — следующий шаг. Мы пропустили это и потеряли день на дебаг проблемы, которая оказалась неправильным projectRef.

🔐

ENV-переменные через Management API

Trigger.dev CLI не имеет команды env push. Только env pull и env list. Для загрузки переменных используйте Management API: POST /api/v1/projects/{ref}/envvars/prod/import с телом { variables: { KEY: VALUE }, override: true }. Важно: чанкуйте по 20 переменных за запрос — большие body вызывают timeout.

🧩

Декомпозиция конвейера на задачи

Один монолитный скрипт 'generate-and-publish' — антипаттерн. Разбейте на атомарные задачи: планирование, генерация текста, генерация изображений, сборка MDX, публикация. Каждая задача принимает минимальный payload (slug + необходимые данные) и возвращает результат. Между задачами — triggerAndWait или batchTriggerAndWait.

🔁

Retry policy для каждого внешнего API

Не один retry policy на все задачи. У OpenAI свой rate limit, у FAL.ai свой cold start, у GitHub API свой timing. Настройте retry индивидуально: LLM — 3 попытки с backoff 5-60 сек. Генерация изображений — 2 попытки с backoff 30-120 сек (cold start!). GitHub — 3 попытки с backoff 3-15 сек.

🔔

Мониторинг и алерты

Dashboard Trigger.dev — это хорошо, но вы не будете сидеть и смотреть на него. Настройте webhook на failed runs → Telegram-бот. Мы используем простой Trigger.dev task, который при ошибке основной задачи отправляет сообщение в Telegram с: slug, этап, ошибка, ссылка на run в dashboard. Время от ошибки до алерта: < 30 секунд.

🛡️

Graceful degradation и fallback

Последний и самый важный шаг. Определите: что критично, а что можно пропустить. Текст статьи — критичен, без него нечего публиковать. Иллюстрации — желательны, но не обязательны: используйте placeholder. Деплой Vercel — можно отложить и батчить. Каждая задача должна знать свой уровень критичности и уметь деградировать.

⚠️

Грабля #1: ENV-переменные

Trigger.dev CLI v4 НЕ имеет команды env set или env push. Только env pull (скачать) и env list (посмотреть). Если вам нужно загрузить 50+ переменных — пишите скрипт для Management API. Мы потеряли полдня, пытаясь найти несуществующую CLI-команду.

Ретраи и восстановление после ошибок
Генерация: FAL.ai FLUX Schnell
#6
💥

Ошибки, которые убивают пайплайн

Антипаттерны из реального опыта — не повторяйте

За полгода эксплуатации Content Factory мы наступили на каждую возможную грабли. Вот коллекция — чтобы вам не пришлось.

⚠️

Антипаттерн: нет дедупликации

Задача упала после генерации, но до записи статуса в базу. Retry создал вторую статью с тем же контентом. Два коммита в GitHub, два деплоя на Vercel, два поста в Telegram. Решение: проверка существования по slug ПЕРЕД генерацией. Используйте idempotencyKey в Trigger.dev или свою проверку в Supabase.

⚠️

Антипаттерн: нет SLA на задачу

Генерация изображений через Replicate иногда занимает 5 минут (cold start GPU). Без timeout задача висит, воркер занят, очередь растёт. Через час — 15 задач в очереди, ни одна не выполняется. Решение: timeout 180 секунд + retry. Лучше перезапустить и попасть на warm instance, чем ждать бесконечно.

💡

Неочевидный баг: часовые пояса в cron

Trigger.dev cron работает в UTC. Мы поставили schedule на ‘0 8 * * *’ думая, что это 8 утра по Москве. Это было 8 утра UTC = 11 утра по Москве. Три дня не могли понять, почему статьи публикуются не когда надо. Всегда указывайте timezone явно или считайте в UTC.

🐛
3
дня потеряно на ENV-баг
📋
12
дублей статей до фикса
🕐
1
инцидент с таймзоной
💾
0
потерянных данных (Supabase спас)
#7
🚀

Деплой и эксплуатация

Один контракт, который не нарушается: код → прод за 60 секунд

Деплой Trigger.dev задач — это одна команда. Серьёзно. Без Docker, без Kubernetes, без CI/CD-пайплайна из 200 строк YAML.

cd ai-core && npx trigger.dev@latest deploy

Эта команда: собирает TypeScript, загружает код на Trigger.dev cloud, версионирует деплой, переключает production на новую версию. Zero-downtime. Задачи, которые выполняются в момент деплоя — дорабатывают на старой версии. Новые задачи подхватывают новую.

🚀
< 60 сек
от git push до прода
🟢
0
downtime при деплое
⌨️
1
команда для деплоя
🔄
версий с мгновенным rollback

Что мониторим в проде:

  • Dashboard Trigger.dev — real-time: текущие runs, очередь, ошибки. Открываешь — видишь всё за 5 секунд.
  • Telegram-алерты — failed runs приходят в чат мгновенно. Со slug, этапом и ссылкой на run.
  • Supabase таблица executions — history: все запуски, статусы, длительность. Для аналитики и дебага.
  • Vercel deploy hooks — подтверждение: статья дошла до прода. Новый билд стартовал.
// Алерт в Telegram при ошибке
export const alertOnFailure = task({
  id: "alert-on-failure",
  run: async (payload: { taskId: string; error: string; slug: string }) => {
    await bot.telegram.sendMessage(
      ALERT_CHAT_ID,
      `Task ${payload.taskId} failed\n` +
      `Slug: ${payload.slug}\n` +
      `Error: ${payload.error}\n` +
      `Dashboard: https://cloud.trigger.dev/runs/...`
    );
  },
});
Деплой и надежность продакшена
Генерация: FAL.ai FLUX Schnell
📊

Экономика Trigger.dev

Hobby plan: $0 (до 50,000 runs/мес). Pro: $50/мес (до 500,000 runs/мес, приоритет, concurrency). Для Content Factory с 2,100 задач в месяц — Hobby хватает с запасом. Сравните с VPS за $30-50, на котором вы потратите 20 часов в месяц на поддержку инфраструктуры. $50/час вашего времени × 20 часов = $1,000 в месяц. Trigger.dev экономит вам $950.

"

Деплой должен быть скучным. Мониторинг должен быть скучным. Если инфраструктура вызывает эмоции — значит, инфраструктура сломана. Trigger.dev сделал наш деплой настолько скучным, что я иногда забываю, что у нас есть фоновые задачи. И это лучший комплимент.

Стас, основатель Atlas CEO

Итог: фоновые задачи — это не код. Это дисциплина.

Trigger.dev не напишет за вас идемпотентную логику. Не придумает retry policy. Не настроит алерты. Это инструмент — как молоток. Молоток не построит дом. Но без молотка дом не построить.

Что Trigger.dev даёт: инфраструктуру, которая не мешает. Retry, timeout, concurrency, observability — из коробки. Dashboard, который показывает реальность, а не абстракцию. Deploy, который работает с первого раза.

Что вы должны дать: дисциплину. Идемпотентность в каждой задаче. Structured logging без исключений. Graceful degradation для каждого внешнего API. Алерты, которые приходят вовремя. И — самое важное — понимание, что production-пайплайн это не «написал и забыл». Это живая система, которая требует внимания. Но с правильным инструментом — минимального внимания.

⚙️
Trigger.dev
оркестрация и инфраструктура
🗄️
Supabase
состояние, дедупликация, история
📱
Telegram
алерты и мониторинг
🌐
Vercel
деплой и доставка контента

Content Factory работает 6 месяцев. 5-10 статей в сутки. 99.4% успешность. Ноль потерянных публикаций. И я сплю спокойно.

Это не магия. Это инженерная дисциплина + правильный инструмент.

📬 Если строите контент-фабрику, агентный контур или AI-пайплайн — подписывайтесь. Разбираем production-паттерны каждую неделю: retry, observability, deploy, масштабирование. Без теории — только то, что работает.

Подписаться в TG →
#Trigger.dev #jobs #оркестрация #идемпотентность #наблюдаемость
Поделиться
Станислав Виниченко

Станислав Виниченко

Основатель Atlas CEO

"Будущее строится сейчас."

📬

Рассылка Atlas CEO

Фронтовые сводки Сингулярности. Каждый день в 9:00. Бесплатно.

Подписаться в Telegram

Atlas Graph

Что открыть дальше

Перелинковка держит пользователя внутри темы: сначала углубляем статью, затем переводим в продукт и следующий шаг.