AWS Lambda · cold & warm · scenario benchmark

AWS Lambda Runtime Benchmark: cold start, warm latency, memory & arm64

scenarios, each doing identical work across the languages that host it (Python and Go skip the two Smithy framework scenarios), swept across memory and CPU architecture, measured cold and warm. The matrix deploys every function as a .zip file archive; container-image cold-start behavior is explored separately on Cold Start Anatomy. The headline cold-start result and the full numeric summary are below; the Comparison page adds warm latency, cost, tail, and architecture, Cold Start Anatomy breaks down what the cold number does and doesn't include, and Rust / Java SnapStart cover their runtime-specific dimensions.
Independent personal project, not affiliated with or endorsed by AWS or any vendor. Best-effort numbers, provided as-is with no guarantee of accuracy. Disclaimer →
Every cold-start number on this site is a floor, not the full wait. The reported cold figure is init (or SnapStart Restore) + the first request's Duration, which is all a REPORT line exposes. Before that clock even starts, the caller also waits through code download + execution-environment setup, latency that appears in no function metric: a roughly constant floor for small packages, growing to a couple hundred ms for the larger packages here, and to of order a second near Lambda's size limit. So the true cold start a caller feels is these numbers plus an unreported term. Cold Start Anatomy measures it →
What the scenarios do & what each one measures
Every scenario is measured both cold and warm, but each is designed to be read on one axis: the handler-shape scenarios (Hello World through Smithy + write flow) on cold start, where setup cost lands; the CPU probes (Letter count onward) on warm latency, where the per-request work shows. The note after each scenario points at that axis.

Filters

Cold start latency vs memory

Total cold-start latency (init or restore + first request) as the memory tier rises, one panel per scenario. Line = P50 (typical), shaded = P10–P90. Lower is better; each scenario has its own y-axis so its shape is readable. Each cell (one series at one memory tier) rests on few samples, one per cold cycle: the handler-shape cells run about 50, the SnapStart cells fewer (each needs a fresh version publish), and the CPU-probe cells as few as 5. A line can therefore vary between adjacent tiers; the appendix sample counts (n) give the basis for a small difference before it is read as real. Rust cells are built with AWS_LC_SYS_NO_JITTER_ENTROPY=1, a latency/security trade-off the Rust page covers with the on-vs-off A/B. The Comparison page covers warm latency, cost, tail, and architecture.

Full latency table: every language and memory tier

The numbers behind the chart: cold and warm latency across every memory tier, with a cell shown only where that runtime and scenario were deployed at that tier (some scenarios have a memory floor, so their lowest tiers are absent). Each phase shows P50 (the typical case) plus the strongest tail its sample count supports: cold is P50 / P90, warm is P50 / P99. Bold = fastest P50; the brightest tail = fastest at that percentile (it can differ from the P50 winner). Spread = slowest ÷ fastest language on P50.
Reading the cold spread: a large cold gap at low memory tiers is partly a lifecycle effect, not only a speed contest. The Lambda Init phase appears to run on boosted CPU, so runtimes that run their setup eagerly at init (e.g. Rust) collect that subsidy, while lazier ones (e.g. Go) defer the same work into the first request, at the memory tier's ordinary, much smaller CPU allocation; put Rust and Go on equal footing and their several-fold low-memory gap narrows to about 1.3x (rough context from a dated off-matrix probe, not this site's benchmark data) — a lifecycle-timing story specific to two runtimes with comparable raw speed, not a general rule that doing everything eagerly erases every cold gap. Cold Start Anatomy → explains the mechanism, what AWS does and doesn't document about it, and how to read these numbers because of it.
Cold percentiles rest on few samples (one per cold cycle, and most warm-axis CPU scenarios run fewer cold cycles than that), so the cold tail is reported as P90 (the same P10–P90 band the chart above shades) rather than a P99 that would sit on under one tail sample. The warm P99 passes the raw n≥ gate but warm samples within a cold cycle are correlated, so read it as a cross-cell comparison; the data appendix carries the full statistical note and the exact per-cell sample counts (n) behind each phase.