VideoCaptions.AI — это бесплатный генератор субтитров с искусственным интеллектом. Пользователь загружает видео, получает транскрипцию с точностью до слова, оформляет анимированные субтитры эффектами и экспортирует результат в MP4. Сервис поддерживает более 30 языков, включая хипглиш, и отлично подходит для создания контента в Instagram Reels, TikTok и YouTube Shorts. Технический стек включает React Router v7 с серверным рендерингом, аутентификацию, Convex в качестве бэкенда, Remotion для рендеринга видео и интеграцию с несколькими сторонними AI-сервисами для распознавания речи.
До недавнего времени приложение полностью работало на Vercel.
Триггер для миграции: лимит CPU
Все изменилось в один уикенд, когда сервис получил неожиданный всплеск трафика. Нагрузка достигла лимита CPU, предусмотренного бесплатным тарифом Vercel — 4 CPU-часа в месяц. Страницы с серверным рендерингом и API-маршруты, обращающиеся к внешним сервисам распознавания речи и языковым моделям, сожгли этот лимит не постепенно, а мгновенно. Приложение просто перестало работать.
Ирония ситуации заключалась в том, что это был хороший знак — продукт набирал популярность. Однако потребовалось хостинговое решение, которое не наказывало бы за успех. Cloudflare уже был частью стека: домен был зарегистрирован там, для хранения файлов использовался R2, а Worker для обработки загрузок уже работал на их платформе. Перенос остальных компонентов выглядел логичным следующим шагом, альтернативой оплате тарифа Vercel Pro за 20 долларов в месяц.
Архитектура мигрируемого приложения
Это не статичный лендинг. Приложение имеет сложную структуру:
- React Router v7 в режиме framework с серверным рендерингом (SSR).
- Более 80 предварительно сгенерированных (prerendered) страниц для SEO (платформенные страницы, сравнения с конкурентами, языковые страницы).
- 5 API-маршрутов, интегрированных с ElevenLabs (распознавание речи), OpenAI (сегментация клипов с помощью LLM) и Groq (резервный провайдер транскрипции).
- Аутентификация с проверкой JWT-токенов как на клиенте, так и на сервере.
- Convex в качестве базы данных (биллинг, кредиты, хранение проектов).
- Remotion для покадрового композитинга видео и экспорта в MP4.
- Upstash Redis для ограничения частоты запросов к API (rate limiting).
Проект организован как монорепозиторий, содержащий 12 приложений и 23 общих пакета. Переносу на Cloudflare Workers подлежало только основное приложение для генерации субтитров, остальные компоненты оставались на Vercel.
Стратегия: постепенный, а не одномоментный переход
Ключевым принципом миграции стал отказ от полного и мгновенного переключения. Процесс был разбит на фазы. Сначала на Cloudflare Workers был развернут новый, параллельный инстанс приложения. Это позволяло проводить тестирование и отладку, не затрагивая рабочую версию на Vercel. Параллельно были настроены правила маршрутизации в Cloudflare, которые направляли определенную долю трафика (например, 5% или трафик от внутренней команды) на новый инстанс для сбора метрик и выявления проблем.
Такой подход минимизировал риски. В случае критических неполадок на новой платформе можно было мгновенно перенаправить весь трафик обратно на стабильную версию Vercel. После успешного тестирования и устранения основных проблем происходило плавное увеличение доли трафика на Cloudflare Workers вплоть до 100%.
Проблемы, с которыми пришлось столкнуться
Перенос выявил ряд несовместимостей и особенностей платформы Cloudflare Workers.
1. Ограничения времени выполнения (Runtime Limits) Самым фундаментальным отличием стала модель выполнения. Vercel Serverless Functions, несмотря на свои лимиты, позволяли выполнять относительно долгие задачи, такие как обработка видео или сложные AI-запросы. Cloudflare Workers имеют жесткий лимит в 30 секунд CPU-времени на HTTP-запрос для тарифа Workers Paid и всего 10 мс для бесплатного тарифа. Это делало невозможным прямой перенос «тяжелых» API-роутов, например, для транскрипции длинных видео.
Решение: Длительные задачи были вынесены в сервис Cloudflare Queues. Вместо непосредственной обработки запроса, Worker помещает задачу в очередь и немедленно отвечает клиенту, что запрос принят в работу. Отдельный Consumer Worker, работающий в фоновом режиме (без ограничения в 30 секунд на выполнение задачи), забирает задачи из очереди, выполняет их, обновляет статус в базе данных Convex и, при необходимости, отправляет уведомление клиенту через WebSocket или по запросу на проверку статуса.
2. Отсутствие статичных prerender-страниц в режиме SSR На Vercel 80+ SEO-страниц генерировались на этапе сборки (prerender) и обслуживались как статические файлы, что было быстро и эффективно. Cloudflare Workers в режиме SSR по умолчанию рендерят каждую страницу динамически при запросе, что увеличивает задержку и нагрузку.
Решение: Для кэширования HTML-ответов был использован Cache API Cloudflare. При первом запросе к странице Worker выполняет SSR, сохраняет полученный HTML в кэш с длительным TTL (время жизни) и возвращает его пользователю. Последующие запросы к той же странице мгновенно обслуживаются из кэша. Для инвалидации кэша при обновлении контента использовались триггеры на основе webhook от системы управления контентом или ручной API-вызов.
3. Работа с файлами и Remotion Библиотека Remotion для рендеринга видео заточена под среду Node.js и имеет специфические зависимости (например, для работы с шрифтами, графикой). Cloudflare Workers основаны на изолированной среде V8 и не предоставляют полного Node.js API или файловой системы.
Решение: Рендеринг видео был оставлен на выделенном сервере (выделенный инстанс на VPS), который запускался по требованию. Cloudflare Worker, получив задание на рендеринг, отправляет метаданные (текст субтитров, стили, параметры) в очередь. Consumer Worker на стороне сервера рендеринга (уже в полноценной Node.js среде) забирает задание, запускает Remotion для создания MP4 и загружает результат обратно в Cloudflare R2, после чего обновляет статус задачи. Это архитектурно более чистое разделение, хотя и добавляет сложности в управлении инфраструктурой.
4. Аутентификация и сессии Механизм аутентификации, основанный на JWT, продолжил работать, так как проверка токенов — это stateless-операция. Однако сессии, хранившиеся в памяти серверных функций Vercel, требовали пересмотра.
Решение: Для хранения сессионных данных был задействован Cloudflare KV — глобальное низколатентное key-value хранилище. KV идеально подошел для хранения временных данных сессии, пользовательских настроек интерфейса или состояния многошаговых форм.
5. Мониторинг и логирование Инструменты мониторинга Vercel не были доступны. Требовалась новая observability-стратегия.
Решение: Для агрегации логов и ошибок была настроена интеграция Workers с Sentry и Datadog. Ключевые бизнес-метрики (количество сгенерированных видео, используемые языки) стали отправляться в Cloudflare Analytics и собственную аналитическую панель, построенную на данных из Convex.
Миграция с Vercel на Cloudflare Workers — это не просто смена хостинг-провайдера, а пересмотр архитектуры под принципиально иную вычислительную модель. Основные сложности связаны с ограничениями времени выполнения Workers, отсутствием полноценной Node.js среды и необходимостью явного управления кэшированием. Однако использование вспомогательных сервисов Cloudflare — Queues для фоновых задач, KV для состояний, R2 для хранения и Cache API — позволяет построить высокопроизводительное, глобально распределенное и экономически эффективное приложение, способное масштабироваться вместе с ростом трафика без неожиданных остановок.