Справочник14 августа 2026 г.·обновлено 14 августа 2026 г.

Cloudflare Workers и Pages для небольших сервисов

Приёмник вебхуков, прокси к API, крон раз в час, форма на статическом сайте — под такие задачи держать VPS дорого по вниманию. Разбор: изоляты вместо контейнеров, привязки вместо строк подключения, wrangler, и где Workers упираются в потолок.

Что это решает

Мелкий сервис — приёмник вебхука, редиректор, прокси к чужому API, обработчик формы, задача по расписанию — требует непропорционально много внимания, если жить ему на отдельной машине. Обновления системы, продление сертификата, мониторинг процесса, бэкапы, счёт за простаивающий сервер. Cloudflare Workers выполняют код на сети Cloudflare без машины, которую надо обслуживать: деплой сводится к одной команде, TLS и раздача по миру уже включены, простой не стоит ничего.

Второе, что снимается, — задержка на холодный старт. Код исполняется в изоляте V8, а не в контейнере, поэтому между приходом запроса и первой строкой обработчика нет запуска среды. Для вебхука, который платёжный шлюз ретраит по таймауту, это разница между «принято» и «повторите».

Как устроено

Изоляты вместо контейнеров

Код выполняется внутри изолята V8 — того же механизма, которым браузер разделяет вкладки. Процесс общий, изоляция на уровне движка. Отсюда следует главное: под ногами не Node.js. Доступен веб-стандартный набор — fetch, Request, Response, URL, Headers, crypto.subtle, TextEncoder, потоки. Флаг совместимости nodejs_compat открывает подмножество встроенных модулей Node (node:buffer, node:crypto и другие), но подмножество, а не весь рантайм.

Точка входа

Worker экспортирует объект с обработчиками:

export default {
  async fetch(request, env, ctx) {
    const url = new URL(request.url);
    if (url.pathname === '/hook') return handleHook(request, env, ctx);
    return new Response('not found', { status: 404 });
  },

  async scheduled(event, env, ctx) {
    await refreshSnapshot(env);
  },

  async queue(batch, env, ctx) {
    for (const msg of batch.messages) await process(msg.body, env);
  },
};

env — объект с привязками и секретами. ctx.waitUntil(promise) позволяет ответить клиенту сразу, а работу доделать после: запись лога, отправка уведомления, прогрев кэша.

Конфиг и дата совместимости

Настройки лежат в wrangler.jsonc (или wrangler.toml):

{
  "name": "hook-receiver",
  "main": "src/index.ts",
  "compatibility_date": "2025-01-01",
  "compatibility_flags": ["nodejs_compat"],
  "kv_namespaces": [{ "binding": "CACHE", "id": "..." }],
  "r2_buckets": [{ "binding": "FILES", "bucket_name": "uploads" }],
  "triggers": { "crons": ["0 * * * *"] }
}

compatibility_date фиксирует поведение рантайма на конкретный срез. Пока она не меняется, обновления платформы не меняют семантику под работающим кодом. Дата ставится той, на которой сервис проверяли, и двигается сознательно, отдельным деплоем.

Привязки вместо строк подключения

Хранилище приезжает в env готовым объектом, а не URL с логином и паролем:

  • KV — ключ-значение, оптимизировано под чтение, согласованность отложенная. Годится для флагов, кэша, справочников, которые меняются редко.
  • D1 — SQL-хранилище на движке SQLite, с транзакциями и подготовленными запросами.
  • R2 — объектное хранилище с S3-совместимым API и без платы за исходящий трафик. Файлы, выгрузки, резервные копии.
  • Durable Objects — именованный единственный экземпляр со строгой согласованностью, собственным хранилищем, будильниками и WebSocket. Точка координации: счётчик, комната, очередь на конкретный ресурс.
  • Queues — асинхронная обработка: приняли вебхук, положили сообщение, ответили, разобрали позже.
  • Service bindings — вызов другого Worker напрямую, без выхода в публичную сеть.
  • Секретыwrangler secret put NAME, дальше env.NAME. В репозитории их нет.

То, что привязка приезжает объектом, убирает целый класс утечек: нечего случайно залогировать и нечего забыть в переменной окружения на чужой машине.

Статика: Pages и ассеты в Worker

Pages подключается к git-репозиторию, собирает проект на своей стороне, раздаёт результат и делает отдельный превью-адрес на каждую ветку. Динамика добавляется файлами в каталоге functions/, где путь файла становится маршрутом.

Параллельно у Workers появилась раздача статики прямо из воркера: статические файлы объявляются в конфиге, всё, что не нашлось среди них, попадает в fetch. Cloudflare сводит оба продукта к Workers, поэтому новый проект проще начинать сразу со второго варианта — один деплой, один конфиг, одна модель логов.

Локальная разработка

wrangler dev поднимает настоящий рантайм локально и эмулирует хранилища на диске. Флаг --remote переключает на реальные привязки в облаке — это единственный способ увидеть настоящее поведение KV с его задержкой распространения.

Деплой, версии, логи

wrangler deploy выкатывает новую версию. Платформа хранит предыдущие: wrangler deployments list показывает историю, wrangler rollback возвращает прошлую. Постепенный выкат позволяет отдать новой версии часть трафика и посмотреть на ошибки до полного переключения. wrangler tail показывает поток логов с прода в реальном времени.

Полезные сценарии

  • Приёмник вебхука: проверить подпись, положить в очередь, ответить 200 за миллисекунды, разобрать асинхронно.
  • Прокси к внешнему API: ключ живёт в секрете воркера, в браузер не попадает, заодно добавляются лимиты и кэш.
  • Редиректы, склейка старых URL и разводка по языку или стране — на границе сети, без правок в основном приложении.
  • Задача по расписанию: раз в час дёрнуть API, сложить снимок в R2, при отклонении послать уведомление.
  • Статический сайт плюс два-три эндпоинта: форма обратной связи, подписка, короткие ссылки.
  • Кэширующий слой перед медленным origin: ответ кладётся в KV или Cache API, тяжёлый бэкенд получает в разы меньше запросов.
  • Бот на вебхуке: приём апдейта, ответ через API мессенджера, состояние диалога в Durable Object.

Ограничения

Процессорное время на запрос ограничено, и потолок различается между тарифами. Тяжёлая обработка изображений, генерация больших PDF, локальный инференс модели в эти рамки не влезают — такие задачи выносятся в отдельный сервис или в очередь с другим исполнителем.

Память и размер бандла тоже ограничены. Приложение с сотней зависимостей туда не соберётся, и «перенесём монолит целиком» — не тот сценарий.

Обычные драйверы баз данных, которым нужен долгий TCP-коннект, напрямую не работают. Для PostgreSQL и MySQL используется Hyperdrive либо драйвер, ходящий по HTTP. Это отдельная настройка, а не «поменяли строку подключения».

Файловой системы нет, локального состояния между запросами нет. Глобальная переменная может пережить несколько запросов, а может исчезнуть в любой момент — изолят пересоздаётся без предупреждения. Всё, что должно жить дольше запроса, уходит в привязку.

KV согласован отложенно: сразу после записи чтение может вернуть старое значение. Счётчики, остатки, балансы через KV не считают — для этого Durable Objects или D1.

Долгоживущих фоновых процессов нет. Демона, который висит и слушает, не запустить; работа режется на обработчики по запросу, крону и сообщениям очереди.

Часть npm-пакетов рассчитана на Node и в бандл не собирается. Проверять совместимость приходится до того, как архитектура на пакет обопрётся.

Привязка к платформе реальна. Durable Objects, KV и Queues не имеют переносимого аналога, и переезд означает переписывание слоя хранения, а не смену хостинга.

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

Как проверить результат

Локально: wrangler dev, затем curl по локальному адресу с теми же заголовками и телом, что шлёт реальный отправитель. Для вебхуков — с настоящей подписью, иначе проверка не покрывает главную ветку кода.

Против реальных привязок: wrangler dev --remote. Здесь ловятся расхождения между локальной эмуляцией KV и его настоящим поведением.

После деплоя открыть wrangler tail и постучать в прод-адрес. Запрос без строчки в логе означает, что до воркера он не дошёл: не тот маршрут, не тот домен, запись DNS не проксируется. Это самая частая причина «код выкатили, а ничего не изменилось».

Сверить конфиг с тем, что тестировали: compatibility_date и список флагов в задеплоенной версии должны совпадать с локальными. wrangler secret list показывает, какие секреты реально существуют в окружении, — отсутствующий секрет даёт undefined, а не ошибку.

Содержимое хранилищ проверяется командами wrangler kv key get, wrangler r2 object get, запросом к D1. Если после обращения к сервису ключ не появился, дело не в чтении, а в записи.

Под нагрузкой посмотреть процессорное время на запрос в наблюдаемости — распределение важнее среднего: потолок бьёт по хвосту, а не по медиане.

Откат проверяется заранее: wrangler deployments list, затем wrangler rollback на стенде. Команда, выполненная впервые в момент аварии, выполняется медленно.

Правило одной строкой: всё, что должно пережить отдельный запрос, хранится в привязке (KV, D1, R2, Durable Object), а глобальная переменная в Worker — только кэш, потеря которого ничего не ломает.

  • cloudflare
  • workers
  • serverless
  • edge