Serverless Architecture: когда это действительно выгодно

Честный разбор serverless с расчетом стоимости и реальными кейсами

Serverless вошёл в моду в 2016-м вместе с AWS Lambda. С тех пор тысячи команд перешли на него, получили счёт на 40 000 ₽ вместо ожидаемых 4 000 ₽ и вернулись обратно к EC2. Другие тысячи команд сэкономили 70% бюджета на инфраструктуру и увеличили скорость деплоя в пять раз. Разница между двумя группами — не в технологии, а в том, подходит ли serverless конкретной нагрузке. Этот материал — не очередной туториал по AWS Lambda. Это разбор экономики serverless с реальными расчётами, антипаттернами и критериями принятия решений. Мы разобрали несколько проектов с бюджетом от 2 до 8 млн ₽, где serverless либо сэкономил деньги, либо их сожрал — и объясним почему. Если вы технический директор или архитектор, который решает, куда укладывать новый сервис — читайте до конца. Если вы менеджер, который хочет понять, когда верить разработчикам, предлагающим serverless — тоже читайте до конца. Что такое serverless на самом деле и почему название обманчиво Серверы никуда не делись. Serverless означает, что вы не управляете серверами — провайдер делает это за вас. Вы пишете функцию, загружаете её, платите только за фактические вызовы. Звучит просто. На практике это означает радикально другую модель исполнения кода. В классической модели у вас есть процесс, который всегда запущен и ждёт запросов. В serverless каждый вызов функции — это потенциально новый контейнер, который поднимается с нуля, исполняет код и умирает. Это называется cold start — холодный старт. При первом вызове (или после периода простоя) функция стартует медленно: 200–2000 мс в зависимости от рантайма и размера пакета. Основные платформы на российском рынке в 2024–2025 годах: Яндекс Cloud Functions — наиболее зрелая российская платформа, поддерживает Node.js, Python, Go, Java, .NET VK Cloud — менее функциональная, но дешевле на простых сценариях AWS Lambda — доступна через зарубежные юрисдикции, всё ещё используется рядом российских команд Selectel Functions — появилась в 2023-м, активно развивается Ключевые характеристики serverless, которые определяют его применимость: Автоматическое масштабирование от 0 до N инстансов — без конфигурации Биллинг за фактическое потребление CPU и памяти (обычно с округлением до 100 мс) Лимит времени выполнения: 5–15 минут в зависимости от платформы Stateless: функция не хранит состояние между вызовами Ограниченный размер пакета (Яндекс Cloud Functions: 300 МБ архив, 512 МБ в памяти) Экономика serverless: точный расчёт для типовых нагрузок Начнём с цифр, потому что именно здесь большинство команд ошибаются. Serverless выгоден не всегда — выгода зависит от паттерна нагрузки. Сценарий 1: API с неравномерной нагрузкой Представим B2B SaaS: 500 активных пользователей, пик нагрузки с 10:00 до 19:00, ночью и в выходные — почти ноль. Средний RPS в рабочее время: 50 запросов в секунду. Средняя длительность запроса: 80 мс. Потребление памяти: 256 МБ. Расчёт для Яндекс Cloud Functions (тарифы 2025 года): # Считаем GB-секунды в месяц Рабочих часов в месяц: 22 дня × 9 часов = 198 часов = 712 800 секунд RPS в рабочее время: 50 Общее число вызовов: 50 × 712 800 = 35 640 000 Средняя длительность: 0.1 с (округление до 100 мс) Потребление: 256 МБ = 0.25 ГБ GB-секунды = 35 640 000 × 0.1 × 0.25 = 891 000 GB-с Нерабочее время (~30% от общего): примерно 200 000 вызовов с пиками Итого GB-секунды: ~1 100 000 Стоимость: 1 100 000 × 0.000013 ₽ ≈ 14 300 ₽/месяц Стоимость вызовов: 35 800 000 / 1 000 000 × 0.4 ₽ ≈ 14 300 ₽/месяц Итого serverless: ~28 600 ₽/месяц Сравниваем с выделенным сервером: # Для 50 RPS с Node.js нужно 2-3 инстанса за отказоустойчивость # Яндекс Cloud, Intel Ice Lake, 4 vCPU, 8 ГБ RAM # 3 инстанса × ~7 500 ₽/месяц = 22 500 ₽/месяц # + Load Balancer: ~1 500 ₽/месяц # Итого: 24 000 ₽/месяц # НО: серверы работают 24/7, ночью и в выходные — впустую # Реальная эффективность использования: ~35% Вывод по сценарию 1: serverless дороже на 20%, но даёт автомасштабирование при всплесках и нулевой overhead на администрирование. Если пиковая нагрузка бывает 500 RPS — serverless уже дешевле, потому что под такой пик потребовалось бы держать 6 серверов. Сценарий 2: Обработка событий — классика для serverless Интеграционный слой: обработка вебхуков от CRM, трансформация данных и запись в базу. 10 000 событий в сутки, среднее время обработки 500 мс, память 128 МБ. Вызовов в месяц: 10 000 × 30 = 300 000 GB-секунды: 300 000 × 0.5 с × 0.125 ГБ = 18 750 GB-с Стоимость вычислений: 18 750 × 0.000013 ₽ ≈ 0.24 ₽/месяц Стоимость вызовов: 300 000 / 1 000 000 × 0.4 ₽ ≈ 0.12 ₽ Итого: менее 1 ₽/месяц (в рамках бесплатного тира) Сервер для той же задачи: минимум 1 500 ₽/месяц. Serverless выигрывает категорически. Сценарий 3: Где serverless убьёт бюджет Тяжёлый ML-сервис: инференс нейросети, время ответа 3 секунды, потребление памяти 2 ГБ, нагрузка 200 RPS равномерно 24/7. Вызовов в месяц: 200 × 86 400 × 30 = 518 400 000 GB-секунды: 518 400 000 × 3 с × 2 ГБ = 3 110 400 000 GB-с Стоимость: 3 110 400 000 × 0.000013 ₽ = 40 435 200 ₽/месяц # Это катастрофа # Выделенный GPU-сервер с A100 в Yandex Cloud: # ~180 000 ₽/месяц (зарезервированный) # Выигрыш выделенного сервера: в 225 раз Правило простое: при равномерной высокой нагрузке serverless всегда проигрывает выделенным серверам. Платить за 100% потребления 24/7 × цену serverless дороже, чем зарезервировать ресурс. Архитектурные паттерны, где serverless даёт реальную выгоду За три года работы с проектами в диапазоне 1–10 млн ₽ мы выделили шесть паттернов, где serverless стабильно даёт преимущество. Event-driven pipelines Классика. Файл загружен в S3/Object Storage → триггер → функция обрабатывает → результат в базу. Здесь serverless идеален: нагрузка нерегулярная, функция stateless, параллельная обработка из коробки. // Пример: Яндекс Cloud Functions — обработка загруженного изображения exports.handler = async (event) => { const { messages } = event; for (const message of messages) { const details = JSON.parse(message.details); const bucketId = details.bucket_id; const objectId = details.object_id; // Загружаем файл из Object Storage const imageBuffer = await downloadFromStorage(bucketId, objectId); // Ресайз + водяной знак const processed = await sharp(imageBuffer) .resize(1200, 800, { fit: 'inside' }) .jpeg({ quality: 85 }) .toBuffer(); // Сохраняем обратно await uploadToStorage(bucketId, `processed/${objectId}`, processed); // Обновляем статус в БД await updateAssetStatus(objectId, 'processed'); } return { statusCode: 200 }; }; Scheduled jobs с низкой частотой Ночной импорт данных, еженедельные отчёты, синхронизация с внешними API раз в час. Держать сервер ради задачи, которая выполняется 5 минут в сутки — расточительство. Serverless-функция по крону: 30 вызовов в месяц, стоимость в рамках бесплатного тира. API-шлюзы и трансформация данных Если у вас несколько внешних API с разными форматами, serverless-функции как адаптеры — чистое решение. Каждый адаптер деплоится независимо, масштабируется под свою нагрузку. Webhooks и callbacks Приём вебхуков от платёжных систем, CRM, мессенджеров. Нагрузка непредсказуема, объём маленький. Serverless-функция отвечает за 50 мс, кладёт событие в очередь и возвращает 200 OK. Идеальный сценарий. Edge-функции и A/B тестирование Персонализация на уровне CDN, геолокационный роутинг, A/B тесты без перезапросов к origin. Cloudflare Workers или аналоги — latency 5–20 мс из любой точки мира, стоимость копеечная. IoT и телеметрия Устройства посылают данные нерегулярно. Serverless-функция просыпается по событию, валидирует и записывает. При 1 000 устройств с 10 сообщениями в час — 720 000 вызовов в месяц, стоимость около 1 000 ₽. Реальные кейсы из практики 404gen Кейс 1: Платформа документооборота, 4.2 млн ₽ Клиент: юридическая компания, 300 сотрудников. Задача: автоматическая генерация PDF-документов по шаблонам + электронная подпись. Нагрузка: 50–200 документов в сутки, пики перед квартальными отчётами. Первоначальная архитектура: монолитный сервис на выделенном сервере. Проблема: 90% времени сервер простаивал, в пиковые периоды очередь росла до 2 часов. Решение с serverless: три функции — валидация запроса, рендеринг PDF (puppeteer), отправка на подпись в УКЭП-сервис. Очередь на базе Яндекс Message Queue. # Результаты после перехода: - Время генерации документа: с 15 мин до 40 секунд - Стоимость инфраструктуры: с 18 000 до 4 200 ₽/месяц (−77%) - Время деплоя нового шаблона: с 2 часов до 10 минут - Инциденты за 8 месяцев: 0 (против 3 в год на монолите) Ключевой момент: puppeteer в Lambda/Cloud Functions — больная тема из-за зависимостей Chromium. Мы собрали кастомный слой (layer) с предкомпилированным Chromium и зафиксировали версию. Это сохранило 3 недели отладки при последующих обновлениях. Кейс 2: Маркетплейс B2B-запчастей, 7.8 млн ₽ Клиент: дистрибьютор промышленных запчастей. Задача: агрегация прайс-листов от 40 поставщиков, нормализация данных, обновление каталога. Поставщики присылают Excel/CSV/XML в разных форматах раз в сутки или по расписанию. Архитектура: каждый поставщик — отдельная функция-парсер. Общая функция-оркестратор запускает их по расписанию. Результаты в общей очереди, функция-нормализатор приводит к единой схеме. # Показатели: - 40 функций-парсеров, каждая деплоится независимо - Добавление нового поставщика: 2 часа вместо 2 дней (монолит) - Стоимость обработки 40 прайс-листов/сутки: ~800 ₽/месяц - Параллельная обработка: все 40 прайсов за 8 минут (vs 2 часа последовательно) - Отказ одного парсера не блокирует остальных Что не сработало: первоначально пытались использовать одну функцию с роутингом по типу поставщика. Это привело к fat function с 180 МБ зависимостей и cold start 4 секунды. Разделение по функции на поставщика решило проблему. Кейс 3: Когда мы отказались от serverless Клиент: финтех-стартап, платёжный процессинг. Первоначальное предложение — serverless API на Яндекс Cloud Functions. Отказались после анализа по трём причинам: Cold start в финтехе недопустим. 500–2000 мс при первом запросе в платёжном сценарии — это потенциальные таймауты на стороне клиента и недовольные пользователи. Provisioned concurrency (прогретые инстансы) убивает экономию. Нагрузка равномерная. 24/7, 100 RPS — serverless здесь дороже в 3–4 раза. Требования к compliance. Полный аудит всех инстансов, конкретные сертификаты — проще с managed Kubernetes. Итог: Kubernetes в Яндекс Managed Kubernetes, 3 ноды, автоскейлинг. Дешевле, предсказуемее, соответствует требованиям. Главные проблемы serverless и как их решать Cold Start Самая частая жалоба. Как минимизировать: Выбирайте лёгкие рантаймы. Node.js и Go стартуют за 100–300 мс. Java и .NET — 1–3 секунды. Python занимает промежуточное место. Уменьшайте размер деплой-пакета. Каждый лишний МБ — это время распаковки. Используйте tree-shaking, не тащите лишние зависимости. Provisioned concurrency / минимальное число инстансов. Держите N прогретых инстансов для критичных функций. В Яндекс Cloud Functions это опция в настройках. Считайте: если функция вызывается реже 1 раза в 10 минут, cold start неизбежен без provisioned. Ленивая инициализация. Не инициализируйте всё в начале файла — только то, что нужно для конкретного вызова. // Плохо: соединение с БД создаётся при каждом холодном старте // и висит в глобальном скоупе без переиспользования // Хорошо: ленивая инициализация с кешированием соединения let dbPool = null; const getDbPool = () => { if (!dbPool) { dbPool = createPool({ host: process.env.DB_HOST, max: 5, // Ограничиваем пул для serverless idleTimeoutMillis: 30000 }); } return dbPool; }; exports.handler = async (event) => { const pool = getDbPool(); // Переиспользуем между вызовами // ... }; Vendor Lock-in Функция, написанная под AWS Lambda API, не запустится на Яндекс Cloud Functions без переработки. Решение — абстракция: // Адаптер-обёртка изолирует vendor-специфику // Ваш бизнес-код не знает о платформе // platform/yandex.js exports.createHandler = (businessLogic) => { return async (event, context) => { const normalizedEvent = normalizeYandexEvent(event); const result = await businessLogic(no