Optimizing AWS Lambda by In-memory Caches using Closures in JavaScript
AWS Lambda users can utilize in-memory caches to improve its performance and reduce the cost.
For example, a secret value stored in your Secrets Manager can be cached outside handler
unless you need the latest value.
This is called static initialization
.
This post shows you how to optimize your AWS Lambda functions by in-memory caches using closures in JavaScript.
Non-optimized Lambda Function
First of all, take a look at the following code.
The key points are:
- It always instantiates
SecretsManagerClient
every invocation. - It always gets a secret value from a Secrets Manager every invocation.
import {
SecretsManagerClient,
GetSecretValueCommand,
} from '@aws-sdk/client-secrets-manager';
export async function handler(event) {
const client = new SecretsManagerClient();
const command = new GetSecretValueCommand({ SecretId: '<YOUR_SECRET_ID>' });
const { SecretString } = await client.send(command);
return {
statusCode: 200,
body: SecretString,
};
}
Run the function a few times, and you will see responses like the following.
In this example, the Duration
is 153.66 ms.
Test Event Name
TestEvent
Response
{
"statusCode": 200,
"body": "{\"message\":\"Hello World\"}"
}
Function Logs
START RequestId: 55f3596f-b4c1-4fcd-bc34-2c63674bd3cd Version: $LATEST
END RequestId: 55f3596f-b4c1-4fcd-bc34-2c63674bd3cd
REPORT RequestId: 55f3596f-b4c1-4fcd-bc34-2c63674bd3cd Duration: 153.66 ms Billed Duration: 154 ms Memory Size: 128 MB Max Memory Used: 89 MB
Request ID
55f3596f-b4c1-4fcd-bc34-2c63674bd3cd
Optimized Lambda Function
Take a look at the following code.
The key points are:
- A function to get a secret value is defined as closure in
useGetSecret
. This function name is inspired by React Hooks. - The secret value is cached at the first call, and always return it until the Lambda runtime is terminated.
- Callers of
getSecret
do not need to be conscious of the cache, leading to separation of concerns.
import {
SecretsManagerClient,
GetSecretValueCommand,
} from '@aws-sdk/client-secrets-manager';
const getSecret = useGetSecret('<YOUR_SECRET_ID>');
export const handler = async (event) => {
const secret = await getSecret();
return {
statusCode: 200,
body: secret,
};
};
function useGetSecret(id) {
const client = new SecretsManagerClient();
const command = new GetSecretValueCommand({ SecretId: id });
let secret = '';
return async () => {
if (secret) {
return secret;
}
const { SecretString } = await client.send(command);
secret = SecretString;
return secret;
};
}
Run the function a few times, and you will see the response like the following.
In this example, the Duration
is 1.28 ms.
It is clear that the cache drastically improve the function performance.
Test Event Name
TestEvent
Response
{
"statusCode": 200,
"body": "{\"message\":\"Hello World\"}"
}
Function Logs
START RequestId: aaba6d16-19ee-437a-9592-f708b3ed7c8b Version: $LATEST
END RequestId: aaba6d16-19ee-437a-9592-f708b3ed7c8b
REPORT RequestId: aaba6d16-19ee-437a-9592-f708b3ed7c8b Duration: 1.28 ms Billed Duration: 2 ms Memory Size: 128 MB Max Memory Used: 88 MB
Request ID
aaba6d16-19ee-437a-9592-f708b3ed7c8b
Conclusion
AWS Lambda users can actively take advantage of in-memory caches to improve its performance and reduce the cost.
I hope you will find this post useful.