Serverless функции и cold start
1) Что такое cold start и почему он возникает
Cold start — дополнительная латентность при создании новой изоляции выполнения (sandbox/контейнер/микро-VM) перед обработкой события. Типичный конвейер:1. Аллокация среды (контейнер/микро-VM, загрузка runtime).
2. Примонтирование VPC/ENI, секретов, файлов, конфигурации.
3. Инициализация кода (импорт модулей, подключение к БД, загрузка моделей).
4. Выполнение хэндлера.
Warm start (reuse) пропускает шаги 1–3. Вероятность cold start растет при пиках, после простоя, при увеличении параллелизма и при обновлениях кода/конфигов.
2) Как измерять и ставить цели (SLO)
Метрики: `init_duration` (инициализация), `duration_total`, «доля холодных запусков», p95/p99 latency, ошибки подключения к зависимостям после простоя.
Снятие телеметрии: логи платформы + собственные метки (например, `cold=true/false` при наличии `context.isColdStart` или собственного флага в статическом замыкании).
SLO-цели (пример): API «логин» p95 ≤ 200 мс, доля cold ≤ 3%; фоновые задания — p95 ≤ 1 с. Для «денежных» маршрутов — отдельные, более строгие.
3) Основные рычаги снижения cold start
3.1 Управление конкарренси и прогрев
Provisioned Concurrency / Min Instances: держит N теплых сред. Используйте для критичных ручек.
Warmers/прогрев: плановые вызовы (cron/scheduler) для удержания воркеров теплыми. Делайте это разумно (регион, время, нагрузка).
Burst-буферы: заранее повышайте лимит параллелизма перед ожидаемыми пиками.
3.2 Упаковка и зависимости
Малый deploy-артефакт: tree-shaking, `--only prod` зависимости, слои (AWS Layers) для крупных либ.
Lazy-init: импортируйте тяжелые модули внутри хэндлера при первом доступе; лениво открывайте соединения.
Теплые ресурсы: кэшируйте клиенты SDK/соединения в глобальной области, чтобы reuse-ить на warm старт.
3.3 Сеть и VPC
Без VPC для функций, которым не нужна приватка (иначе ENI-attach добавляет десятки-сотни мс).
Если VPC обязателен — используйте VPC-эконом режим провайдера (ENI-пулы/оптимизация), proxy к БД (RDS Proxy/Cloud SQL Auth Proxy) и connection pooling.
3.4 Языки и рантаймы
Node.js/Go стартуют быстрее всего; Python — обычно быстро, но чувствителен к большим импортам; Java/.NET— тяжелее без GraalVM/AOT и профиляции.
Для JVM рассмотрите SnapStart/CRaC/Graal Native; для.NET — trimmed Self-Contained.
3.5 Инициализация и state
Дорогую инициализацию вынесите в инициализационный хук (init phase), а не в путь запроса.
Применяйте on-demand загрузку конфигов/секретов с локальным кэшем (TTL).
Не храните пользовательский state в памяти — только кэш-сигналы/коннекторы.
4) Архитектурные паттерны, уменьшающие влияние cold start
4.1 Асинхрон и очереди
Принимаем запрос → валидируем → кладем в очередь/шину (SQS/PubSub/Queue Storage) → отвечаем 202/Accepted → обрабатываем фоном.
Подходит для неинтерактивных операций (выплаты, отчеты, тяжелые вычисления).
4.2 Precompute/Pre-cache
Генерация доступов/каталогов/фич-флагов заранее по триггерам (CRON/события) и хранение в KV/кэше/edge.
4.3 Fan-out/Fan-in
Разбиваем долгую операцию на несколько коротких функций (Map/Reduce-подобно) → меньше риск таймаутов и повторного cold.
4.4 Edge-offload
Простейшие проверки (JWT/HMAC, гео-редирект, антибот) выполняем на edge (Workers/Functions@Edge), чтобы экономить RTT и разгружать origin.
5) Практика: конфиги и приемы
5.1 AWS Lambda (provisioned + RDS Proxy)
hcl
Terraform sketch: enable provisioned concurrency on the sales version of the resource "aws_lambda_provisioned_concurrency_config" "api" {
function_name = aws_lambda_function. api. function_name qualifier = aws_lambda_alias. prod. name provisioned_concurrent_executions = 20
}
RDS Proxy for connection pool "aws_db_proxy" "rds_proxy" {
name = "pg-proxy"
engine_family = "POSTGRESQL"
idle_client_timeout = 1800 require_tls = true
}
Node.js (ленивая инициализация и reuse):
js let pgClient ;//reuse between warm runs let cold = true;
exports. handler = async (event, ctx) => {
const isCold = cold; cold = false;
if (!pgClient) {
const { Client } = await import('pg'); // lazy import pgClient = new Client({ host: process. env. PG_PROXY, ssl: true });
await pgClient. connect();
}
const t0 = Date. now();
const data = await pgClient. query('select 1');
return {
statusCode: 200,
headers: { 'x-cold-start': String(isCold), 'x-elapsed-ms': String(Date. now()-t0) },
body: JSON. stringify({ ok: true })
};
};
5.2 GCP Cloud Run / Cloud Functions (min instances)
yaml
Cloud Run service. yaml apiVersion: serving. knative. dev/v1 kind: Service metadata: { name: api }
spec:
template:
metadata:
annotations:
autoscaling. knative. dev/minScale: "5" # keep warm run containers. googleapis. com/cpu-throttling: "false"
spec:
containerConcurrency: 80 containers:
- image: gcr. io/proj/api:latest env:
- { name: DB_HOST, value: "10. 0. 0. 5" }
5.3 Azure Functions (AlwaysOn/PreWarm)
Premium/Elastic планы с AlwaysOn; pre-warmed instances ≥ прогнозного p95 параллелизма.
6) Таймауты, ретраи, дедлайны
Общий дедлайн (client-side) передавайте через заголовок (`x-deadline-ms`/`grpc-timeout`), внутри функции укорачивайте `per-hop timeout`.
Повторы только для идемпотентных операций; используйте Idempotency-Key и дедупликацию.
Для API фронта — hedging (дублирующий запрос спустя p90) и circuit breaker на дальние зависимости.
7) Работа с БД/кэшами/секретами
Пулы/прокси (RDS Proxy/Cloud SQL Proxy/pgBouncer) вместо тысяч коротких коннектов.
Короткие TTL секрета + в памяти кэш с фоновым обновлением.
Кэш (Redis/Memcached/KV): догрузка «тяжелых» справочников на init, но с ограничением по времени.
8) Организация кода и сборка
Отдельные хэндлеры на узкие use-case’ы; один «толстый» бандл = долгий init.
ESBuild/Rollup: исключайте неиспользуемое, объединяйте только критичное.
Слои (Layers/Extensions) — для больших либ (OpenSSL модели, SDK), чтобы переиспользовать кэш провайдера.
9) Тестирование и симуляция пиков
Синтетика «холодных» запуска: принудительно выключайте min instances и гоняйте параллельный трафик ступеньками.
A/B: сравнивайте долю cold, p95, ошибку коннекта к БД/секретам, затраты.
GameDay: пиковая нагрузка ×2 от исторического максимума, отключение прогрева.
10) Стоимость (FinOps)
Min instances/provisioned concurrency стоят денег — включайте только для горячих маршрутов.
Снижайте продолжительность выполнения: кэш, короткие таймауты, отказ от ненужных SDK.
Учитывайте egress (вызовы к внешним API) и логирование (объем логов быстр растет на пиках cold).
11) Антипаттерны
Один монолитный хэндлер с десятками мегабайт зависимостей.
Обязательное подключение к БД на каждом вызове (без reuse/proxy).
VPC для всех функций «на всякий случай».
Длинные таймауты и слепые ретраи → «хвосты» и фантомные списания.
Прогрев «всего подряд» круглосуточно.
Тайная инициализация в пути запроса (лентисья init > 100 мс — выносите в init/кэш).
12) Специфика iGaming/финансов
Пути денег (депозиты/выводы): держите provisioned/min instances, отдельные SLO, строгое ограничение таймаутов и повторов (идемпотентность обязательно).
KYC/PSP: нестабильные внешние API — оборачивайте в queue + worker, на фронте — 202/поллинг/вебхук.
Регуляторика и аудит: неизменяемые логи (WORM), журнал входящих событий с `Idempotency-Key`, корреляция `trace_id`.
Data residency: функции, обрабатывающие PII, разворачивайте в региональных аккаунтах/проектах; никаких edge-кэшей с PII.
13) Чек-лист prod-готовности
- Определены SLI/SLO: p95/p99, доля cold, целевые значения по маршрутам.
- Включены provisioned/min instances на критичных функциях; прогноз конкарренси.
- Бандл минимизирован; тяжелые либы вынесены в слои; lazy-import/инициализация.
- Reuse клиентов SDK/БД; настроен RDS/SQL Proxy; пул соединений.
- VPC только где нужно; ENI/прокси оптимизированы; секреты через менеджер + локальный кэш TTL.
- Таймауты/дедлайны/ретраи: backoff+джиттер; только идемпотентные повторы.
- Синтетика «cold» + нагрузочные тесты; алерты на рост доли cold и p99.
- Runbooks: как увеличивать provisioned, как менять minScale, как включать деградацию.
- Для iGaming: отдельные SLO/дашборды «пути денег», Idempotency-Key, WORM-аудит.
14) TL;DR
Cold start неизбежен, но управляем: держите теплые инстансы там, где важно, уменьшайте бандл, применяйте lazy-init и reuse соединений, избегайте лишнего VPC, выносите тяжелые операции в очереди/воркеры и используйте edge для легких правил. Для критичных финансовых путей — отдельные SLO, идемпотентность и строгие таймауты; измеряйте долю cold и включайте прогрев только там, где это окупается.