I have a questions about how the finally block executes in a node js application running in a lambda as I am observing some werid behavour.
I have an AWS lambda API endpoint written in node/express/typescript that is suppose to save any thrown errors into a DynamoDb table.
The logic to put the error object into DDB inside a finally block as shown by below pseudocode.
async getById(req: Request, res: Response): Promise<void> {
try {
throw error
} catch (error) {
print error
return response to user
} finally {
save error to dynamo DB
}}
Flow is: User -> CloudFront -> Api Gateway -> Lambda -> Application -> getByID method(throws an error) -> Dynamo DB
Below are the observations:
- 1st Api invocation -> 1st error thrown -> Nothing appears in DDB
- 2nd Api invocation -> 2nd error thrown -> 1st error shows up in DDB, but not the 2nd
- 3rd Api invocation -> 3rd error thrown -> 1st, and 2nd error shows up in DDB, but not the 3rd
And so on. So the pattern is, current error never shows up in Dynamo DB unless a new invocation of the Api occur.
I have tried below to no avail:
- Running the code within finally with and without async await
- Waiting for over 20 mins for the error to show up in DDB
So my questions are:
- If finally block is guaranteed to run assuming the behaviour is same as in Java, why doesn't it for the 1st API invocation
- Why do subsequent API invocations cause the previous error to show up?
- How does returning the response to user work when there is a finally block, how does the event loop behave in such a case since Node JS is single threaded
It sounds like the execution context is being frozen once you return a value and the finally block is not running until the context is unfrozen for the next invocation. Lambda does not implicitly wait for the node event loop to empty before freezing the context. You can explicitly tell Lambda to wait to return until the event loop is empty. However, I would suggest you don't do that. If you want to consistently write the error to your DB you will have to write it before returning a response.
Further reading: https://docs.aws.amazon.com/lambda/latest/dg/nodejs-context.html https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtime-environment.html