Сценарий

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.

Одна платформа для API и расписаний

Один ID функции может питать HTTP-маршрут и шаг пайплайна по расписанию — без дублирования деревьев кода.

Cron проверяется при сохранении; планировщик помнит следующий запуск пайплайна — правки расписания переносятся аккуратно.

crontab, systemd timers, Kubernetes CronJob и Inquir

Выбор планировщика зависит от зрелости эксплуатации и того, где уже живёт остальной стек. Таблица сравнивает четыре типичных подхода к повторяющейся бэкенд-работе — не edge-cron и не субсекундные тики.

crontab, systemd timers, Kubernetes CronJob и Inquir
Критерийcrontabsystemd timersKubernetes CronJobПайплайны Inquir по расписанию
Настройка и сопровождениеПравка crontab на хосте; выражение не проверяется при сохраненииUnit- и timer-файлы; надёжнее срабатывание, но упаковка всё ещё на уровне хостаYAML-манифесты и работающий кластер — даже для одной ночной задачиCron на триггере пайплайна; выражение проверяется при сохранении
История запусковПеренаправление stdout в файл или почту root — без структурированного аудитаjournalctl по unit; при росте числа задач — grep по сервисамЛоги подов и статус Job; хранение зависит от стека логирования кластераЗаписи вызовов рядом с HTTP — без SSH и ручного поиска
Ретраи при сбоеНет встроенных — следующий тик единственный «неявный» повторOnFailure= перезапускает unit; политики ретраев нет в продуктовом UIbackoffLimit у 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 в спецификации CronJobSkip-if-running и ключи идемпотентности в хендлере или дизайне пайплайна
Когда уместноОдна VPS, один инженер, скрипты уже работают и редко падаютLinux-команды на systemd, готовые копать journalПродукт уже на Kubernetes с GitOps и логированием кластераCron и REST на одной платформе — история и ретраи без YAML кластера

Расписание, ретраи и наблюдаемость

Проверка cron при сохранении

Некорректное выражение отклоняется при сохранении, а не «внезапно» в проде.

Шаг планировщика и перекрытия

Нагрузка минутного масштаба; для длинных задач — пропуск при уже идущем запуске и явные правила перекрытия.

История запусков

Видно, отработала ли задача, без поиска по логам на сервере.

Оповещения

Подключите мониторинг к доле ошибок или к SLA по длительности выполнения.

Чеклист миграции

Безопасно перенесите одну повторяющуюся задачу из shell в выполнение по расписанию в пайплайне.

1

Вынести хендлер из shell-скрипта

Перенесите логику скрипта в версионируемую функцию.

2

Ручной вызов и подключение расписания

Сначала проверьте результат вывода, затем добавьте триггер расписания.

3

Защита от перекрытий и алерт на сбой

Предотвратите порчу данных при параллельных запусках и сразу показывайте сбои.

Типовые паттерны cron-задач

Два распространённых паттерна: инкрементальная синхронизация с курсором (безопасно повторять) и генерация отчёта с веерной рассылкой.

jobs/incremental-sync.mjs (watermark pattern)
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 };
}
jobs/nightly-report.mjs (report + fan-out)
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), и учитывайте переход на летнее время, если расписание привязано к бизнес-часам.