The cold start is the moment a fresh container must do everything a running one already did: boot the OS, start the runtime, load the code, and then answer one user's request. The total is the sum of stages, and each stage has a price. Walk a Lambda-style cold start.
trace stepSystem
A request arrives for a function with zero warm instances. The platform picks a host, reserves resources (CPU quota, memory), and pulls the image — cached layers on the host, so the pull is usually the delta: 50–200ms for cached base layers, seconds for uncached. In Lambda's architecture this stage also includes network plumbing and security-group setup, which is part of why cold starts aren't just "docker run."
trace stepSystem
The process starts: the OS loads the binary and its shared libraries, the JVM or Node or Python interpreter spins up. A JVM cold boot is 300–800ms before your code runs a line; Node and Python are 50–150ms; a Go binary ~20ms. This stage is pure overhead — none of it is your code, and most of it is the language's fault. The single biggest lever here is language choice, not tuning.
trace stepSystem
Your handler module is imported: dependency graphs resolve, config is read, DB connection pools initialize, SDK clients construct. This is the stage that surprises people — a Lambda with 30 imports and a DB pool can spend 200–400ms here. The classic cold-start tax is the eager connection pool: every cold start opens database connections the warm path never needs.
trace stepSystem
The platform registers the handler, sets up the invocation plumbing (event loop, error channel, response serializer), and — in Lambda's model — signals readiness. One subtlety: the platform doesn't wait for your first request to finish; it reports "init complete" at the end of this stage, which is why billed init time and your perceived cold start can differ.
trace stepSystem
The request executes: handler logic, downstream calls, response. This first request carries the whole startup cost, so the p95 user experiences init + runtime + load + request. Numbers on Lambda's Node.js path: ~200–800ms cold vs ~5–30ms warm for the same handler — a 20–100x gap that lives entirely in the stages above. The JVM path: 1–3s cold, ~30–60ms warm.
trace stepSystem
The instance survives; the platform reuses it for the next request. Warm requests skip every stage above — they are plain function calls. Keep-alive strategies (Lambda's provisioned concurrency, long-running server processes, idle-timeout tuning) exist to convert cold requests into warm ones, at the price of paying for idle instances.
The ledger: every cold start pays image pull + runtime boot + code load + wiring before the user's request even begins, and every one of those stages is fixed overhead per instance — no traffic volume amortizes it. The entire discipline of cold-start engineering — snapshots, provisioned concurrency, lazy init, AOT — is the attempt to move those four stages from "per instance" to "once," so the first request a user sees costs what the millionth costs.