Serverless cron-задачи на той же платформе, что и ваши API
Запускайте cron-задачи как пайплайны по расписанию: история запусков рядом с HTTP-вызовами, настраиваемые ретраи и общие секреты и логи — ночная работа использует те же функции, что и ваши REST-эндпоинты.
Обновлено: 2026-06-28
Кратко
Суть ответа
Serverless cron-задачи на той же платформе, что и ваши API. Один ID функции может питать HTTP-маршрут и шаг пайплайна по расписанию — без дублирования деревьев кода.
Когда подходит и когда нет
- Ночной ETL
- Ротация сертификатов/токенов
- Периодический опрос интеграций
На что обратить внимание
- Таймеры повышают надёжность срабатывания, но не дают изоляции зависимостей и общих с HTTP-хендлерами секретов и логов.
- Всё равно нужно одно место для ретраев, истории запусков и алертов — иначе задачи по расписанию остаются невидимыми рядом с продакшен-API.
Ситуация: нагрузка и где обычно ломается
Почему crontab и hosted-cron подводят
- VPS crontab: output routed to root mail; no built-in retries
- systemd timers: reliable firing, but scattered logs and manual secrets
- Kubernetes CronJob: solid primitives with cluster overhead for small teams
Если вывод заданий уходит лишь в почту root или в локальные логи без централизованного мониторинга, сбои могут длительно оставаться незамеченными.
Когда расписание живёт только на одной VPS, расхождение версий окружения и секретов, а также вопрос «кто и когда менял cron», почти неизбежно превращают каждый инцидент в ручной разбор по SSH.
Записи в crontab редко проходят тот же конвейер версионирования, что основной код: сложно восстановить, какая именно сборка выполнялась в запланированное время.
Параллельные запуски одних и тех же заданий без явных правил перекрытия и блокировок повышают риск порчи общего состояния — к расписаниям в пайплайне стоит относиться с той же аккуратностью, что и к обработчикам webhooks.
Когда простых рецептов недостаточно
Почему одних таймеров недостаточно
Таймеры повышают надёжность срабатывания, но не дают изоляции зависимостей и общих с HTTP-хендлерами секретов и логов.
Всё равно нужно одно место для ретраев, истории запусков и алертов — иначе задачи по расписанию остаются невидимыми рядом с продакшен-API.
Как Inquir помогает в этом сценарии
Одна платформа для API и расписаний
Один ID функции может питать HTTP-маршрут и шаг пайплайна по расписанию — без дублирования деревьев кода.
Cron проверяется при сохранении; планировщик помнит следующий запуск пайплайна — правки расписания переносятся аккуратно.
Сравнение
crontab, systemd timers, Kubernetes CronJob и Inquir
Выбор планировщика зависит от зрелости эксплуатации и того, где уже живёт остальной стек. Таблица сравнивает четыре типичных подхода к повторяющейся бэкенд-работе — не edge-cron и не субсекундные тики.
| Критерий | crontab | systemd timers | Kubernetes CronJob | Пайплайны Inquir по расписанию |
|---|---|---|---|---|
| Настройка и сопровождение | Правка crontab на хосте; выражение не проверяется при сохранении | Unit- и timer-файлы; надёжнее срабатывание, но упаковка всё ещё на уровне хоста | YAML-манифесты и работающий кластер — даже для одной ночной задачи | Cron на триггере пайплайна; выражение проверяется при сохранении |
| История запусков | Перенаправление stdout в файл или почту root — без структурированного аудита | journalctl по unit; при росте числа задач — grep по сервисам | Логи подов и статус Job; хранение зависит от стека логирования кластера | Записи вызовов рядом с HTTP — без SSH и ручного поиска |
| Ретраи при сбое | Нет встроенных — следующий тик единственный «неявный» повтор | OnFailure= перезапускает unit; политики ретраев нет в продуктовом UI | backoffLimit у Job; настраивается в манифесте, не рядом с историей API | Число ретраев и задержка на каждом шаге пайплайна |
| Секреты | .env на сервере или inline в shell — общие для всех задач на хосте | EnvironmentFile в unit; ротация по-прежнему вручную на каждом хосте | Kubernetes Secrets — нативно для кластера, но отдельно от auth шлюза приложения | Секреты workspace, общие с HTTP-маршрутами — без параллельного .env на сервере |
| Изоляция между задачами | Один UNIX-пользователь и окружение интерпретатора — конфликты зависимостей типичны | Можно запускать от разных пользователей; всё равно одна машина, общее ядро | Под на запуск — сильная изоляция, когда кластер уже оправдан | Контейнер на вызов — та же модель изоляции, что у синхронных HTTP-хендлеров |
| Версионирование вместе с кодом | Строки crontab часто вне конвейера деплоя | Unit-файлы могут быть в git; расхождение между хостами всё равно случается | Манифесты в git/GitOps — отлично, когда K8s уже control plane | Бандлы функций и конфиг пайплайна версионируются вместе с деплоем платформы |
| Многошаговые сценарии | Shell-скрипты с цепочкой команд — непрозрачные точки сбоя | Отдельные unit или bash в ExecStart — ручная оркестрация | Один контейнер на CronJob; DAG требуют Argo/Workflows и аналогов | Графы пайплайнов с рёбрами — extract, transform, load отдельными узлами-функциями |
| Перекрытие / длинные прогоны | Ручной flock или надежда — параллельные запуски портят общее состояние | Настройки concurrency на unit — логику всё ещё пишете сами в хендлере | concurrencyPolicy Forbid/Replace в спецификации CronJob | Skip-if-running и ключи идемпотентности в хендлере или дизайне пайплайна |
| Когда уместно | Одна VPS, один инженер, скрипты уже работают и редко падают | Linux-команды на systemd, готовые копать journal | Продукт уже на Kubernetes с GitOps и логированием кластера | Cron и REST на одной платформе — история и ретраи без YAML кластера |
Что вы получаете на платформе
Расписание, ретраи и наблюдаемость
Проверка cron при сохранении
Некорректное выражение отклоняется при сохранении, а не «внезапно» в проде.
Шаг планировщика и перекрытия
Нагрузка минутного масштаба; для длинных задач — пропуск при уже идущем запуске и явные правила перекрытия.
История запусков
Видно, отработала ли задача, без поиска по логам на сервере.
Оповещения
Подключите мониторинг к доле ошибок или к SLA по длительности выполнения.
Что сделать дальше, по шагам
Чеклист миграции
Безопасно перенесите одну повторяющуюся задачу из shell в выполнение по расписанию в пайплайне.
Вынести хендлер из shell-скрипта
Перенесите логику скрипта в версионируемую функцию.
Ручной вызов и подключение расписания
Сначала проверьте результат вывода, затем добавьте триггер расписания.
Защита от перекрытий и алерт на сбой
Предотвратите порчу данных при параллельных запусках и сразу показывайте сбои.
Пример кода
Типовые паттерны cron-задач
Два распространённых паттерна: инкрементальная синхронизация с курсором (безопасно повторять) и генерация отчёта с веерной рассылкой.
export async function handler(event) { // Read cursor from env so re-runs do not re-process old records const since = process.env.SYNC_CURSOR ?? new Date(Date.now() - 86_400_000).toISOString(); const records = await source.fetchUpdatedSince(since); await destination.upsertBatch(records); // idempotent by record ID const newCursor = records.at(-1)?.updatedAt ?? since; // Update cursor in your config/store for next run return { synced: records.length, cursor: newCursor }; }
export async function handler(event) { const rows = await buildReport(); await storage.upload(rows, { key: `reports/${new Date().toISOString().slice(0, 10)}.csv` }); // Fan out — each recipient gets a separate pipeline step await Promise.all( recipients.map((r) => global.durable.startNew('send-report', undefined, { recipientId: r.id, rowCount: rows.length })), ); return { rows: rows.length, notified: recipients.length }; }
Когда подходит и когда нет
Выбирайте этот сценарий, когда…
Когда это уместно
- Ночной ETL
- Ротация сертификатов/токенов
- Периодический опрос интеграций
Когда лучше выбрать другое
- Субсекундные периодические задачи — сверяйтесь с таймерами платформы
Вопросы и ответы
Вопросы и ответы
Что если запуск cron длится дольше интервала?
Используйте ключи идемпотентности, распределённые локи или защиту skip-if-running внутри хендлера, чтобы перекрывающиеся запуски не портили общее состояние.
Чем это лучше crontab на одной машине?
Вы получаете версионируемые бандлы функций, изоляцию контейнера на каждый вызов, сохранённую историю запусков и ту же модель секретов, что у HTTP-функций, — плюс многошаговые графы, когда одно расписание должно разветвляться.
Какой часовой пояс у cron-выражений?
Зафиксируйте часовой пояс, который ожидает команда (для бэкендов часто UTC), и учитывайте переход на летнее время, если расписание привязано к бизнес-часам.