SaaS-компаниям постоянно нужно выжимать больше производительности и платить меньше за инфраструктуру. Serverless-технологии снимают рутину управления, позволяя командам сосредоточиться на продукте и бизнес-ценности. Но по мере роста систем и требований выигрывать дальше можно только через постоянную оптимизацию — и техническую, и финансовую.

В этом материале — путь Smartsheet: какие ограничения им пришлось учитывать, какое решение они собрали и как достигли снижения задержек более чем на 80%. Практическая история для тех, кто развивает serverless-архитектуру под высокие нагрузки и хочет предсказуемую производительность за разумные деньги.

Обзор решения

Smartsheet — крупная облачная корпоративная платформа для управления работой. Ею пользуются миллионы людей по всему миру: планирование, исполнение, трекинг, автоматизация и отчётность в масштабе организации.

В основе платформы — событийно-ориентированная архитектура, обрабатывающая действия пользователей в реальном времени для разных типов документов. Платформа коллаборативная: над одним документом могут одновременно работать несколько человек. Любое изменение порождает цепочку событий, которую нужно провести с минимальной задержкой — чтобы сохранять согласованность данных и давать интерфейсу мгновенную обратную связь. Стабильно низкая латентность — базовое бизнес-требование: иначе проседают UX и продуктивность.

Профиль нагрузки типичен для рабочего дня: днём — «пила», ночью и по выходным — затишье. В пике активность за минуты может вырасти с сотен до десятков тысяч событий в секунду. Под такой профиль Smartsheet использует serverless-конвейер на Amazon SQS и AWS Lambda. Эластичность этих сервисов позволяет автоматически масштабироваться под всплески и также автоматически схлопываться в непиковые часы — что позволяет выигрывать и по скорости, и по затратам.

На схеме ниже — высокоуровневая архитектура конвейера обработки событий Smartsheet.

high-level architecture of the Smartsheet event processing pipeline
Высокоуровневая архитектура конвейера обработки событий Smartsheet.

Возможность для оптимизации

В Smartsheet функции AWS Lambda выполняют и пакетные задачи, и обработку API-запросов. Основной рантайм — Java. Lambda сама масштабирует число исполняющих окружений под текущий трафик: если есть свободное — запрос летит туда, если нет — создаётся новое.

Инициализация нового окружения — не мгновенна. При старте код функции ходит во внешние зависимости — базы данных, REST API и пр. Эти обращения добавляют задержку на запуск.

«Чтобы снизить задержку клиентских запросов и не раздувать бюджет, мы задействовали подготовленную параллельность (Provisioned Concurrency) в Lambda с автомасштабированием и перешли на Graviton. В итоге P95-задержка упала на 83%, при этом мы продолжаем масштабировать платформу и её пределы».

На схеме ниже показано, как функции Lambda обращаются к внешним зависимостям во время инициализации.

Lambda functions reach out to external dependencies during initialization
Функции Lambda обращаются к внешним зависимостям во время инициализации.

Именно это и есть «холодный старт». Пусть он и затрагивает в среднем <1% вызовов, у Smartsheet жёсткие требования к латентности, поэтому даже такие «хвосты» пришлось вычищать.

Устранение холодного старта с помощью подготовленной параллельности

Чтобы срезать задержки на инициализацию, команда Smartsheet включила в архитектуру подготовленную параллельность (Provisioned Concurrency). Смысл простой: вы задаёте, сколько исполнителей Lambda нужно держать «тёплыми», чтобы принимать вызовы сразу. На схеме ниже показана разница.

Без подготовленной параллельности окружения поднимаются по требованию — иногда (обычно <1% вызовов) это означает ожидание создания окружения и выполнения стартового кода. С подготовленной параллельностью Lambda заранее поднимает и инициализирует нужное число исполнителей, так что входящие вызовы почти всегда попадают в уже «разогретые» окружения. Результат — предсказуемая латентность и исчезновение редких, но болезненных хвостов.

invocations are served by warm execution environments
Вызовы обслуживаются тёплыми (уже разогретыми) окружениями выполнения.

В Provisioned Concurrency есть динамический механизм «перелива» (spillover), который страхует от всплесков трафика. Когда входящий поток превышает заданный лимит «тёплых» исполнителей, лишние вызовы переходят на параллельность по требованию (on-demand concurrency), а не упираются в троттлинг. Масштабирование получается плавным, сервис остаётся доступным даже на пиках, при этом большинство запросов по-прежнему обслуживаются разогретыми окружениями.

В Smartsheet выставили значение подготовленной параллельности на уровень исторического P95 по конкурентности. Эффект был мгновенным: холодные старты резко просели, а P95-задержка упала на 83%. Дальше мониторинг показал ещё один резерв: функции активно вызываются в рабочие часы, а ночью и по выходным почти простаивают — это видно на следующем графике.

Lambda functions were heavily used during work hours but had significantly fewer invocations at night and on weekends
Функции Lambda активно использовались в рабочие часы, а ночью и по выходным число вызовов было заметно ниже.

Статическая Provisioned Concurrency отлично держала пиковые часы, но ночью и по выходным «тёплые» окружения простаивали. Чтобы поднять утилизацию и снизить стоимость, команда пошла дальше: включила автомасштабирование под реальный трафик и перевела функции на архитектуру AWS Graviton.

Автомасштабирование подготовленной параллельности и переход на Graviton

Есть два способа использовать Provisioned Concurrency:

  • Статика. Задаёте фиксированное число предварительно инициализированных окружений. Хорошо для предсказуемого трафика. Минусы: в пиковые периоды возможно недовыделение ресурсов (часть вызовов уходит в on-demand и ловит холодные старты), в простое — недоиспользование.

  • Автомасштабирование. Конфигурация меняется по метрикам загрузки: число «тёплых» окружений автоматически растёт или падает вслед за спросом. Это повышает утилизацию и даёт лучший профиль «производительность/стоимость» при «пиловом» трафике.

На схеме ниже — сравнение статической и динамической Provisioned Concurrency.

static and dynamic provisioned concurrency
Статическая и динамическая подготовленная параллельность

Чтобы улучшить соотношение «стоимость/эффективность», Smartsheet перевела Provisioned Concurrency на автомасштабирование по фактической нагрузке. Чтобы масштабировать подход на сотни функций, всё оформила как код (IaC) в Terraform: общие политики, единые правила.

Политики следят за метрикой LambdaProvisionedConcurrencyUtilization и масштабируют «тёплые» окружения по разным порогам в зависимости от типа нагрузки:

  • Интерактивные API — порог 60%: заранее подготавливаем исполнителей, держим сверхнизкую латентность и устойчивость к всплескам.

  • Асинхронные пайплайны — порог 90%: максимизируем утилизацию и экономию.

На схеме ниже — как эти политики привязаны к типу нагрузки и уровню использования подготовленной параллельности.

auto scaling policies based on provisioned concurrency utilization rate and workload type
Политики автомасштабирования на основе уровня использования подготовленной параллельности и типа нагрузки

Ещё один шаг — смена процессорной архитектуры функций AWS Lambda с x86_64 на arm64 (Graviton). Для этого Smartsheet поставила ARM-версии используемых слоёв (Datadog, Lambda Insights): бинарники, собранные под одну архитектуру, как правило, не совместимы с другой.

Сами функции у Smartsheet — на Java, упакованы в JAR, поэтому при переезде на Graviton проблем совместимости не возникло. Инфраструктура описана в Terraform, так что переключение архитектуры свелось к изменению одного свойства в ресурсах aws_lambda_function (см. следующий фрагмент кода).

property change in aws_lambda_function resources
Изменение свойства в ресурсе(ах) aws_lambda_function

Переезд на Graviton дал Smartsheet −20% к стоимости выполнения функций (метрика ГБ·с). Детали — в разделе цен AWS Lambda.

Лучшие практики

Чтобы ужать холодные старты и платить меньше без просадки в скорости, держите в арсенале следующее:

  • Тонкая настройка функций AWS Lambda. Подбирайте объём памяти под профиль нагрузки: вместе с памятью растёт и доля CPU. Часто это ускоряет выполнение и в сумме снижает стоимость (меньше миллисекунд × чуть больше ГБ·с = выгоднее).

  • Архитектура Graviton2 для совместимых ворклоадов. ARM-платформа даёт лучшее соотношение цена/производительность; прирост — до 34% в зависимости от типа нагрузки.

  • Борьба с холодными стартами: Provisioned Concurrency + Lambda SnapStart. Начните со статического порога по исторической конкурентности, отслеживайте утилизацию и подключайте автомасштабирование — так выйдете на оптимальный профиль «стоимость/производительность».

Заключение

Serverless на AWS Lambda и Amazon SQS снимает с команд заботы об инфраструктуре и масштабировании, освобождая время для продукта. Кейс Smartsheet показывает: сочетание Provisioned Concurrency и Graviton заметно снижает задержки (улучшая UX) и параллельно сокращает расходы — по сути, готовая дорожная карта оптимизации для всей организации. Независимо от масштаба — поддерживаете ли вы крупные корпоративные системы или запускаете новые облачные сервисы — эти проверенные приёмы помогают одновременно нарастить производительность и повысить экономическую эффективность serverless-решений.


Когда система растёт, часто всё сводится к одной и той же боли: очереди под нагрузкой, конфиги, которые живут своей жизнью, и метрики, на которые уже никто не смотрит. Если после кейса Smartsheet хочется разобрать практические приёмы вокруг очередей, конфигураций и наблюдаемости — приходите на демо-занятия от преподавателей Otus (это бесплатно):

  • 20 ноября, 18:00 — Kafka как очередь задач: создаём систему асинхронной обработки. Записаться

  • 24 ноября, 20:00 — Применение распределённых конфигураций для управления микросервисами на Go. Записаться

  • 27 ноября, 19:00 — Метрики и Prometheus. Записаться

Немного практики в тему — пройдите вступительный тест по Инфраструктуре высоконагруженных систем и узнаете, есть ли пробелы в знаниях.

Комментарии (1)


  1. DanielKross
    14.11.2025 09:04

    Масштабирование не 100% эффективное к сожалению. Перидически тупит, лагает, и иногда "проблемы с загрузкой". Неторопливое приложение.