cold-start-budget-reference
Pure-reference catalog of cold-start budgets across serverless runtimes. Covers AWS Lambda's three-phase cold start (Init: download+unzip+runtime-bootstrap; Init code: imports + module load; Invoke: handler execution), Cloudflare Workers' isolate model (sub-millisecond cold starts via V8 isolates per developers.cloudflare.com), Vercel Edge Runtime, Lambda SnapStart for JVM (snapshot-restore for Java), and provisioned-concurrency trade-offs. Includes per-runtime typical cold-start ranges and the testable behaviours each model creates. Use when designing latency budgets, choosing a runtime, or auditing cold-start variance in production.
Install with skills.sh (any agent)
npx skills add testland/qa --skill cold-start-budget-referencecold-start-budget-reference
Overview
Per aws.amazon.com/blogs/compute on cold starts (opens in new window), Lambda's cold start has three phases:
Phases 1 + 2 are the "cold" part. Phase 3 is what runs every invocation (cold or warm).
When to use
How to use
Per-runtime cold-start budgets
Per AWS, Cloudflare, Vercel docs (typical ranges; bigger packages and bigger memory-class skew higher):
| Runtime | Typical cold start | Architecture |
|---|---|---|
| AWS Lambda Node.js (256MB) | 200-700ms | Container (Firecracker microVM) |
| AWS Lambda Python (256MB) | 250-800ms | Container |
| AWS Lambda Java 11 (512MB, no SnapStart) | 1.5-6s | Container + JVM warmup |
| AWS Lambda Java 11 (512MB, SnapStart) | 100-300ms | Snapshot-restore per docs.aws.amazon.com/lambda (opens in new window) |
| AWS Lambda .NET (1GB) | 1-3s | Container + .NET runtime |
| AWS Lambda Go (256MB) | 100-300ms | Container; pre-compiled binary |
| AWS Lambda Rust (256MB) | 50-200ms | Container; pre-compiled binary |
| Cloudflare Workers | 0-5ms (V8 isolate spawn) | V8 isolate per developers.cloudflare.com/workers (opens in new window) |
| Vercel Edge Runtime | 5-30ms | V8 isolate (similar to Workers) |
| Vercel Node.js Functions | 200-500ms (small) to 2-3s (large) | Lambda under the hood |
| Netlify Functions | 300ms-2s | Lambda under the hood |
The "Workers / Edge" qualitative leap is the isolate model: each function is a V8 isolate, spun up in microseconds per developers.cloudflare.com (opens in new window) - no container, no OS startup.
Mitigations
Provisioned concurrency (AWS Lambda)
Per docs.aws.amazon.com/lambda (opens in new window): keeps N execution environments pre-initialised. Eliminates cold starts up to N concurrent requests; you pay for the keep-warm time.
Trade-off: cost. A constant N=10 provisioned concurrency for 30 days ≈ $30-300 depending on memory class.
Lambda SnapStart (Java / .NET)
Per docs.aws.amazon.com/lambda/latest/dg/snapstart.html (opens in new window): takes a snapshot of the initialised JVM and restores from it on each cold start. Reduces Java cold starts from 1.5-6s → 100-300ms.
Caveats:
Package-size discipline
Lambda cold-start scales with deployment-package size. Per AWS: keep under 50MB (zipped) → cold start in the 200-800ms range. Larger packages → seconds.
Avoid heavy module-level imports
Init code runs once but on every cold start. Heavy imports (database connection pool init, large dependency trees) inflate init time.
# Bad: top-level
import heavy_lib # 2s import time
def handler(event, ctx):
return heavy_lib.do_thing(event)
# Better: lazy-import
def handler(event, ctx):
import heavy_lib
return heavy_lib.do_thing(event)Lazy imports add per-warm-call latency but reduce cold-start spike.
Runtime choice
Pre-compiled runtimes (Go, Rust) have far lower cold starts than managed runtimes (Java, Python). For latency-critical paths, runtime choice is a primary lever.
Testable behaviours
| Behaviour | Test |
|---|---|
| Cold start within budget | Force cold (deploy or wait > idle-evict time); measure p95 first-invocation latency |
| Warm performance | Subsequent invocations (50+) → p95 well within prod budget |
| SnapStart effective | Pre/post SnapStart cold start delta |
| Provisioned concurrency keeps warm | Run for an hour; no cold-start spikes observed |
| Package size in budget | Build-step assertion: zipped artifact < 50MB |
| No heavy init-time imports | Profile init phase; assert < 500ms |
Worked example
A Java 11 Lambda (512MB) serves a low-traffic checkout callback. Users report occasional multi-second waits, though the dashboard p95 looks healthy.
Result: the cold-start tail drops from ~5s to the 100-300ms range with no provisioned-concurrency spend.
Anti-patterns
| Anti-pattern | Why it fails | Fix |
|---|---|---|
| p99 latency surprise | Cold starts at the tail; not visible in p50/p95 | Watch p99; explicit cold-start monitoring (CloudWatch Init Duration metric) |
| Large dependency tree on init path | Cold start inflated 2-5x | Audit imports; lazy-import non-critical |
| Java on Lambda without SnapStart | 5s cold starts | Enable SnapStart |
| Provisioned concurrency without size analysis | Pay for unused warm instances | Tune to actual concurrency p99 |
| Cold-start test only on the local dev environment | Local doesn't simulate Lambda init | Deploy + test against AWS / Workers / Edge |
| Treat cold starts as "rare" | Bursty traffic → cold starts cluster | Account for both steady-state and burst patterns |
| Ignore module bundling | Webpack-bundled is smaller AND has fewer import resolution hops | Bundle for production Lambdas |
Limitations
References
Related skills
aws-sam-local-testing
Wraps AWS SAM (Serverless Application Model) Local CLI for testing Lambda functions locally: `sam local invoke` (single invocation with event payload), `sam local start-api` (local API Gateway emulator), `sam local start-lambda` (local Lambda invoke endpoint for AWS SDK clients), and event-payload generation (`sam local generate-event`). Use when testing Lambda + API Gateway + integrated AWS services locally.
azure-functions-tests
Runs Azure Functions locally using Azure Functions Core Tools v4 (`func start`), Azurite storage emulation, and framework-native unit tests for handler code (.NET isolated worker model, Node.js v4, Python v2). Covers HTTP, queue, and timer trigger testing, admin-endpoint invocation for non-HTTP triggers, and binding verification via local.settings.json. Use when testing Azure Functions before deployment, reproducing trigger behaviour without live Azure services, or gating function handler logic in CI.
cloudflare-workers-miniflare
Wraps Miniflare 3 (the official Cloudflare Workers simulator) and Wrangler dev for testing Workers locally. Covers Miniflare's getMiniflare() programmatic API (workerd-backed simulation matching prod), the wrangler dev local-mode (live-reload during dev), KV / Durable Objects / R2 / D1 bindings emulation, and Vitest + @cloudflare/vitest-pool-workers for in-process tests. Use when testing Cloudflare Workers code locally.
lambda-test-tools-net
Wraps Amazon.Lambda.TestTool (the canonical .NET Lambda local-testing toolkit from github.com/aws/aws-lambda-dotnet) for invoking Lambda handlers from xUnit / NUnit tests with simulated AWS Lambda contexts (ILambdaContext, ILambdaSerializer). Covers handler-direct invocation, mock context fixtures, the dotnet-lambda CLI, and integration with the .NET LambdaSerializer for JSON. Use when testing AWS Lambda functions written in C#/.NET.
lambda-timeout-budget-reference
Pure-reference catalog of AWS Lambda timeout + billing semantics. Covers Lambda's hard 15-minute (900s) wall-clock limit, the timeout-vs-deadline relationship (Lambda Context.getRemainingTimeInMillis), per-invocation billing (rounded to 1ms; per-invocation + duration × memory), the memory-vs-CPU relationship (CPU scales linearly with memory), the integration-timeout cascade (API Gateway 29s → Lambda 15min; SQS visibility-timeout vs Lambda timeout), and per-runtime nuances. Use when designing a Lambda's timeout config, debugging timeout-vs-billing surprises, or sizing memory for compute-bound workloads.
netlify-functions-tests
Wraps Netlify Functions testing patterns: Netlify Dev (`netlify dev`) for local routing emulation, the @netlify/functions handler API testing pattern, Netlify Edge Functions (Deno runtime) vs Background Functions (Lambda under the hood) distinction, and scheduled-function (cron) test patterns. Use when testing Netlify Functions or Edge Functions.
serverless-framework-test-plugin
Wraps the Serverless Framework (serverless.com) test ecosystem: serverless-offline (local HTTP emulator), serverless-jest-plugin / serverless-mocha-plugin (per-runtime test runners), and the `serverless invoke local` CLI for one-off invocations. Use when testing Lambda functions deployed via the Serverless Framework.
serverless-integration-test-builder
Workflow-driven skill that builds the integration-test suite for a serverless application from its IaC definition (SAM template / serverless.yml / Wrangler config / Vercel functions / Netlify functions). Walks through: identifying the function inventory + event sources, picking the right local-emulator per function (sam local / Miniflare / netlify dev / vercel dev / serverless-offline), generating test events per event source, asserting on cold-start + timeout budgets, and emitting the test directory + CI config. Use when introducing integration tests to a serverless project.
vercel-edge-runtime-testing
Wraps Vercel Edge Runtime testing patterns: the @edge-runtime/jest-environment + edge-runtime CLI for executing Web-Standard APIs (Request / Response / fetch) in jest tests, the `vercel dev` local emulator for full route testing, and the Edge vs Node Function divergence (no fs, no Buffer; Request / Response only). Covers the 30s Edge function timeout per vercel.com/docs. Use when testing Vercel Edge Functions or middleware.