I understand that await is a very efficient way to allow other code in the event loop execute while the current function is waiting on a long-running task. It can be very useful in web apps, where one API call shouldn't block everything else. However, if I have a simple Lambda, where I call an Api and return the response, what does the Lambda function do when the Javascript event loop is not executing anything?
First, each Lambda can only handle one request at a time. So, it's not like that while the handler is blocked, another handler could swoop in and execute.
Second, the Lambda function can't exit until the await is done, which means that I'll be billed for the entire execution time.
Is there some optimization that I don't know about, or is awaiting in Lambda pretty much the same as synchronous execution? I find this strange since awaiting on an API call, doing some processing, and returning is a pretty common pattern for microservices on Lambda, and it seems simple to run other instances while one is blocked. Is my understanding incorrect?
PS: This answer is based on AWS Lambda NOT running on Managed Instances (launched in Nov 30, 2025).
However, if I have a simple Lambda, where I call an Api and return the response, what does the Lambda function do when the Javascript event loop is not executing anything?
It sits and waits. If new requests don't arrive for some period of time, the execution environment is shutdown. You can read more about it in Lambda execution environment lifecycle.
First, each Lambda can only handle one request at a time. So, it's not like that while the handler is blocked, another handler could swoop in and execute.
Precisely!
Second, the Lambda function can't exit until the await is done
This behavior actually depends on the flag context.callbackWaitsForEmptyEventLoop. Quoting the documentation:
Set to false to send the response right away when the callback runs, instead of waiting for the Node.js event loop to be empty. If this is false, any outstanding events continue to run during the next invocation.
And your following affirmation
which means that I'll be billed for the entire execution time.
Is correct as well.
Is there some optimization that I don't know about, or is awaiting in Lambda pretty much the same as synchronous execution?
It's not an "optimization" in itself. The advantage of using it is that it allows you to await for multiple things at the same time instead of executing each of them serially (in sequence). The execution time then becomes the duration of your longest task instead of the sum of all your tasks.