This is a scheduled post, and that is fine. It goes live on September 15, 2026. Right now the only way to see it is a direct link, so you got it from me or someone I shared it with. Feel free to pass it along.

The Lambda Bug That Only Shows Up on Warm Starts

Lambda reuses your execution environment across warm invocations, so anything cached outside the handler, tokens, counters, mutable state, is still sitting there from the last request. Why that's the reason clients belong outside the handler and request-specific values belong inside it.

chaotictoejamSeptember 15, 2026

The second video in my AWS micro-learnings series, "Lambda in almost 60 Seconds." It breaks Lambda down to the essentials: event in, code runs, response out, environment disappears. All that is true for a cold start. But there is a caveat..

What happens when the environment doesn't actually disappear?

So, here's the deeper dive.

AWS reuses your execution environment across invocations. When it can do this, it's called a warm start, and it's why you're told to put things like your DynamoDB client outside the handler. For exmple:

// Created ONCE and reused across warm invocations
const dynamoClient = new DynamoDBClient({});

export const handler = async (event: APIGatewayProxyEvent) => {
  // this runs on EVERY invocation
  const result = await dynamoClient.send(new GetItemCommand({ ... }));
  return { statusCode: 200, body: JSON.stringify(result) };
};

This is the recommended pattern. You reuse a warm connection, and it is faster and cheaper than creating a new one every time. But there is a gotcha.

Cold start vs warm start timeline diagram

A cold start pays the init cost once. A warm start skips straight to the handler, and whatever you set up outside it (e.g. cached tokens, in-memory counters, mutable variables) is still sitting there from the last invocation. If you write code that assumes a clean slate every time, you'll ship a bug that only reproduces under real traffic and never in a quick manual test. That's because manual tests usually hit cold starts.

The rule of thumb: clients and connections live outside the handler. Anything request-specific lives inside it. If a value needs to be fresh every time, don't let it live above the function line.