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 і включайте прогрів тільки там, де це окупається.