Skip to content

Asynchronous initialization with provisioned concurrency

0

Goal

I want to do asynchronous work during the initialization phase of a Node 22-based lambda with provisioned concurrency enabled, as described here:

https://aws.amazon.com/blogs/compute/operating-lambda-performance-optimization-part-1/

Problem

I'm finding that the initialization phase only runs until the first asynchronous action, then freezes indefinitely until the first request comes in, resulting in slow run time on the initial request.

Caveats

I can work around this by pinging the lambda periodically, but would rather not.

Details

I am the only user of the lambda, and it's configured with provisioned concurrency using an alias. What I'm finding is that my provisioned environment is warming up when I expect, but is not completing the initialization work, which is roughly:

async function warmup() {
    console.log("Warmup: Fetching secrets")
    const secret = await fetchSecretFromSecretsManager()
    console.log("Warmup: Fetching database")
    await connectToDatabase(secret.databaseConfig)
    console.log("Warmup: complete")
  }

// This call is at the top-level of the module, and I can confirm that it's entering the warmup function during initialization.
warmup();

// ...the handler follows and works as expected, so I'm not including it here

From the logs, I am seeing "Warmup: Fetching secrets" during the initialize phase, and then the Lambda runtime reports that it's successfully initialized. At this point there is no further activity no matter how long I wait -- seconds, minutes, hours. When I issue my first request to the lambda, I see the rest of the warmup logging (which adds several seconds to the processing time).

I'm asking for confirmation that my approach is valid and good, as well as help understanding what I'm doing wrong.

Some things I've tried:

  • Using void warmup()
  • Using warmup().then(...).catch(...)

asked a year ago220 views

3 Answers
0
Accepted Answer

Your approach is on the right track, but there's a key issue with how you're handling asynchronous initialization in Lambda with provisioned concurrency.

When using provisioned concurrency, Lambda initializes the execution environment ahead of time, but there's a critical detail about how asynchronous code behaves during initialization. The initialization phase isn't guaranteed to wait for asynchronous tasks to complete unless you use specific patterns.

For Node.js functions, the recommended approach is to deploy your code as an ECMAScript module (ES module) and use top-level await to ensure all initialization is completed during the function's INIT phase. This ensures that your asynchronous initialization tasks are fully completed before any handler invocations.

Here's how you should modify your approach:

  1. Use ES modules by either:
  • Changing your file extension to .mjs
  • Or specifying "type": "module" in your package.json
  1. Use top-level await in your initialization code:
// Top-level await (only works in ES modules)
console.log("Warmup: Fetching secrets");
const secret = await fetchSecretFromSecretsManager();
console.log("Warmup: Fetching database");
await connectToDatabase(secret.databaseConfig);
console.log("Warmup: complete");

// Export your handler
export const handler = async (event) => {
// Your handler code
};

Without using ES modules and top-level await, your asynchronous initialization tasks may not complete during the INIT phase, which explains why you're seeing the initialization process pause after the first async call and only resume when the first actual invocation occurs.

This approach will maximize the effectiveness of provisioned concurrency by ensuring all initialization is truly completed during the INIT phase, eliminating cold start latency from your function invocations.
Sources
Building Lambda functions with Node.js - AWS Lambda
How Smartsheet reduced latency and optimized costs in their serverless architecture | AWS Architecture Blog
Configuring provisioned concurrency for a function - AWS Lambda

answered a year ago

AWS
EXPERT

reviewed a year ago

0

I started down this path and gave up at the 80% mark because it was turning into a bit of work and I couldn't find any documentation that it would help. But I'll go back to this and report results.

answered a year ago

0

I confirmed that this is correct. I did a quick test version of my lambda that mocks a few delays and saw it complete fully before initializing the lambda.

answered a year ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.