A cold start is the delay that occurs when a serverless or scale-to-zero platform has no warm instance available and must create a new execution environment before it can handle a request. It includes provisioning the sandbox, loading code, starting the runtime and running initialization code, and shows up as extra latency on the first request.
What a cold start is
Serverless platforms such as AWS Lambda, Google Cloud Run and Azure Functions run your code in execution environments they create on demand. When a request arrives and a warm environment is available, the platform reuses it and only your handler runs. When none is available, because the function was idle, traffic just increased or a new version was deployed, the platform must build a new one first. That extra work is the cold start, and the request that triggers it pays the full price in latency.
Cold starts typically affect a small share of requests, but they concentrate exactly where it hurts: in the tail of the latency distribution, after deployments and during traffic spikes.
What happens during a cold start
On AWS Lambda the lifecycle of an environment has an Init, an Invoke and a Shutdown phase. A cold start covers everything before the first Invoke:
- Environment creation. The platform allocates a sandbox (a Firecracker microVM on Lambda, a container instance on Cloud Run) and downloads the code package or container image.
- Runtime start. The language runtime boots, for example the JVM, the .NET CLR, Node.js or Python, plus any Lambda extensions.
- Function initialization. Your code outside the handler runs: imports, dependency injection, SDK clients, database connections, configuration and secrets loading.
Lambda reports this phase as Init Duration in the REPORT log line of the first invocation. Since 1 August 2025, AWS also bills the Init phase for on-demand functions using ZIP packages on managed runtimes, so cold starts now have a direct cost as well as a latency impact.
What makes cold starts longer
| Factor | Effect |
|---|---|
| Runtime | JVM and .NET runtimes usually start more slowly than Node.js, Python or compiled Go and Rust binaries. |
| Package or image size | More code and dependencies mean more to download, unpack and load. |
| Initialization code | Framework bootstrapping, eager connection pools and reflection-heavy dependency injection add time. |
| Memory setting | On Lambda, CPU is allocated in proportion to memory, so small functions also initialize with less CPU. |
| Container start (Cloud Run) | The container must start and listen on its port before it receives traffic. |
How to measure cold starts
The OpenTelemetry semantic conventions for FaaS define the boolean span attribute faas.coldstart, set to true on the first invocation of a new instance. With it you can split latency by cold and warm invocations instead of guessing from averages:
- Cold start rate: share of invocations with
faas.coldstart = true, per function and version. - Init duration: distribution of initialization time, ideally as p50, p95 and p99 percentiles.
- User impact: end-to-end latency of requests that hit a cold start, seen in the trace from the caller's perspective.
Correlate cold start rate with deployments and concurrency. A spike right after every release is expected; a steady high rate at constant traffic usually points to scaling behavior or idle timeouts.
How to reduce cold starts
- Pre-warmed capacity. Lambda Provisioned Concurrency keeps a configured number of environments initialized; Cloud Run uses minimum instances; Azure Functions offers pre-warmed or always-ready instances in its Premium and Flex Consumption plans. All of these trade cost for predictability.
- Snapshots. Lambda SnapStart, available for Java, Python and .NET, restores an initialized environment from a snapshot instead of running Init again.
- More CPU at startup. Cloud Run's startup CPU boost allocates extra CPU while the container starts; on Lambda, a higher memory setting has a similar effect.
- Lean code. Trim dependencies, avoid scanning the classpath at startup, initialize clients lazily and reuse them across invocations.
- Light instrumentation. Choose telemetry layers and agents designed for serverless and measure their effect on Init duration.
Cold starts beyond serverless
The same effect appears wherever capacity scales from zero or new instances start under load. Kubernetes workloads that scale to zero with Knative or KEDA pay for image pulls, container start and readiness probes before the first request is served. JVM services also have a warm-up phase after startup: until the JIT compiler has optimized hot code paths and caches are filled, the first minutes of a new pod are slower than its steady state. Treat these cases like serverless cold starts: tag new instances, compare their latency with established ones and include warm-up in rollout and autoscaling decisions.
Common mistakes
Looking only at average duration hides cold starts completely. Scheduled "keep-warm" pings are fragile: they keep one environment warm, not the many that a traffic burst needs. And moving heavy work into the handler to shorten Init only shifts the delay to the first request of each environment.
How Obseria helps
Obseria's serverless monitoring ingests OpenTelemetry traces from functions, so faas.coldstart and Init durations can be analyzed per function, version and region and set against the latency of the calling services. For AWS, Obseria collects metrics from 300+ services agentlessly, including AWS Lambda.