ColdStartTimeout

Serverless Cold Start Timeout: Fix Lambda Hangs on First Invocation

Server & Cloud Intermediate 👁 10 views 📅 Jun 17, 2026

Your serverless function times out on first call because the runtime hasn't finished initializing. The fix: bump the timeout to 30s and lazy-load dependencies.

You're not alone — cold starts are a pain

You deploy a function, hit the endpoint, and it hangs for 30+ seconds before timing out. The second call works fine. That's the cold start timeout. Here's what's actually happening and how to fix it.

The fix: give it enough runway

The most common cause is a timeout value too low for the startup work your runtime does. The default Lambda timeout is 3 seconds — that's fine for warm invocations, but a cold start often needs 10-15 seconds just to initialize the runtime and load dependencies.

  1. Increase the timeout to 30 seconds — go to your function configuration and set timeout to 30s (or more if you have heavy dependencies). I usually start at 15s and bump to 30s if needed. On AWS Lambda, that's in the function's Basic Settings. On Azure Functions, check the functionTimeout in host.json. On GCP Cloud Functions, it's under the function's General settings.
  2. Lazy-load heavy dependencies — don't import everything at the top of your function. Instead, load modules inside the handler only when they're needed. Example in Node.js:
    exports.handler = async (event) => {
    // lazy load the heavy DB client
    const { DynamoDBClient } = await import('@aws-sdk/client-dynamodb');
    const client = new DynamoDBClient({ region: 'us-east-1' });
    // rest of handler
    };
  3. Use provisioned concurrency if nothing else works — only do this after trying steps 1 and 2 because it costs money. On Lambda, set Provisioned Concurrency to 1. On Azure, use Premium Functions with pre-warmed instances. On GCP, use min instances. This keeps a function warm 24/7.

Why step 1 works

What's actually happening here is that Lambda's execution environment needs to bootstrap the runtime, install any layers, load your code, and execute the handler. The default timeout assumes your code runs instantly — but the first invocation includes all that overhead. AWS Lambda, for example, has a Init phase that runs INIT_START to INIT_REPORT. If your timeout expires during this phase, you get a 502 or 504. Increasing the timeout lets the init phase finish.

Why step 2 works

Node.js and Python import everything at module scope by default. That means loading entire frameworks like AWS SDK v3 or heavy ORM libraries before the handler even starts. By lazy-loading, you defer that work until the line actually executes. In Node.js, dynamic import() returns a promise, so the runtime can start handling the request while modules load in the background. On Python, using import inside the handler does the same thing — the import cache means subsequent calls are near-instant.

Less common variations of the same issue

ScenarioWhat's differentFix
VPC-hosted function with NAT gatewayCold start includes ENI attachment, which can take 10-30 secondsUse VPC endpoints or move to VPC-less if possible. Otherwise increase timeout to 60s and use provisioned concurrency.
Function using Lambda LayersLayer extraction adds 1-5 seconds per layer on first invocationCombine layers into one, or move logic into the deployment bundle. Reduce layer count.
Container-based functions (Lambda with ECR)Cold start includes pulling the container image (even if cached, it can be slow)Use smaller base images (Alpine, distroless). Set ImagePullPolicy: Always can hurt — use IfNotPresent if you control the orchestration.
Functions with large node_modulesnpm install includes many small files — cold start sees filesystem overheadBundle your code with esbuild or webpack. Or use .nft files for Node.js to include only what's used.
Edge functions (CloudFront Functions, Cloudflare Workers)Cold start is usually under 50ms, but complex JS can trip timeoutsKeep code under 1ms execution time. Use synchronous operations only — no async/await in edge runtimes.

Prevention: stop the cold start from ever being a problem

First, understand that cold starts are a fact of serverless life. You can't eliminate them — only manage them.

  • Set realistic timeouts from day one. I default to 30s for any new function. You can tighten later after testing warm performance.
  • Design for stateless initialization. Don't connect to databases or run migrations inside the handler initialization. Move those to the handler itself, and use connection pooling.
  • Use language-specific optimizations: For Node.js, use --enable-source-maps and bundle with esbuild. For Python, use @lru_cache on expensive calls. For Java, use SnapStart (Lambda) which takes a snapshot after init and restores from it — cuts cold start from 10s to under 1s.
  • Monitor cold start latency with tools like AWS X-Ray or Datadog. Set a custom metric for ColdStartDuration. If it's consistently over 5 seconds, you need provisioned concurrency or a smaller dependency footprint.
  • Warm your functions with a scheduler — a CloudWatch Events rule that pings your function every 5 minutes keeps it warm. It's a hack, but it works. Don't rely on it in production — use provisioned concurrency instead.

The real lesson: cold start timeouts aren't a bug — they're a design constraint. Give your function the time it needs to initialize, lazy-load what you can, and use provisioned concurrency for critical paths. Your users won't wait 30 seconds — but your code will.

Was this solution helpful?