TL;DR
⚡ Deploy Bun in AWS Lambda swiftly and efficiently with SST's streamlined process.
🐰 Dive into the integration of Bun with Lambda through SST and evaluate its readiness for your use-case.
1️⃣ Load the Bun Layer to your AWS Account
💡 Before you start, ensure you have an AWS account and that you're logged in via the AWS CLI.
To verify your login status, execute the following command:
aws sts get-caller-identity
If you are not logged in, run the command below:
aws configure
We'll be utilizing the official Bun layer for Lambda, provided by the Bun team 🐰.
Follow the instructions listed on the Bun Layer page to add the layer to your AWS account.
When executing bun publish-layer, ensure you choose the aarch64
architecture ⚡!
bun run publish-layer -- \
--arch aarch64 \
--region eu-west-1
Afterward, navigate to your AWS console, access the Lambda service, and verify that the layer is available.
Make a note of its ARN; we'll be using it later. 🧠
2️⃣ Deploy a new SST app 🔥
SST is a framework designed to streamline the deployment of Serverless applications on AWS. If you're curious about why we favor SST over the Serverless Framework, check out our previous article: Best Serverless Framework in 2023: A Data-Driven Showdown for AWS Projects
Proceed with the steps in SST's standalone get started section.
In essence, you'll execute:
npx create-sst@latest my-sst-app
Install your dependencies and then deploy your app (we already made sure you are logged in via the AWS CLI 😉). It will run cdk bootstrap under the hood so you don't have to worry about it.
📝 For a quick test of Bun in Lambda, consider removing all resources in
MyStack.ts
except the lambda resource. We'll adjust it later.
Upon completion, your app should be deployed with a Node.js Lambda function. Next, we'll modify your stack resources to make the lambda run Bun!
3️⃣ Add the Bun Layer to your lambda, and execute bun 🐰
Let's incorporate some Bun code into our Lambda.
First, add this to your tsconfig.json
{
"compilerOptions": {
"types": ["bun-types"] // add Bun global
}
}
Then, draft a basic lambda handler leveraging the Bun.password
API (this ensures Bun is operational!):
let hashedPassword = null;
export default {
async fetch(request: Request): Promise<Response> {
const { password, action } = (await request.json()).event as {
password: string;
action: "get" | "set";
};
switch (action) {
case "set":
hashedPassword = await Bun.password.hash(password);
return new Response(
JSON.stringify({
statusCode: 200,
body: { result: "Password has been set." },
})
);
case "get":
const isVerified = await Bun.password.verify(password, hashedPassword);
return new Response(
JSON.stringify({
statusCode: 200,
body: { result: isVerified },
})
);
}
},
};
💡 In the above code, the password is set in Lambda's memory. The variable will be lost whenever a new instance of this lambda is created.
Now, it's time to deploy our modifications! 🚀
In your MyStack.ts
file, add the following code:
new Function(stack, "my-bun-function", {
// 👇 This is required to use custom runtimes
runtime: Runtime.PROVIDED_AL2,
handler: "lambda.fetch",
// 👇 That's why we published bun layer with aarch64 architecture
architecture: Architecture.ARM_64,
code: Code.fromAsset("out"),
memorySize: 1024,
timeout: Duration.seconds(10),
layers: [
LayerVersion.fromLayerVersionArn(
stack,
"bunLayer",
// 👇 Replace with your layer ARN
YOUR_BUN_LAYER_ARN
),
],
});
Lastly, in your package.json
file, refresh the deploy
command to:
"deploy": "bun build --outdir=out packages/functions/src/PATH_TO_YOUR_HANDLER --target bun && sst deploy"
💡 If you need to deploy several lambdas, a dedicated build step to minify bun code would be necessary!
Now, run your deploy
command, and go check your lambda in the AWS console. You should be able to test it with an input event that matches the one we used in our code.
{
"password": "my-password",
"action": "set"
}
To take it a step further, connect your Lambda to an API Gateway, or generate a function URL via the AWS console for testing!
4️⃣ Conclusion & Caveats 🥲
Using the custom Bun Layer comes at a cost: ~500ms cold start time. 🥶
After conducting tests on computationally intensive tasks ( calculating Fibonacci sequences), I observed performance to be twice as slow compared to the native Node.js runtime. 🐢
Personally, I believe Bun in Lambda isn't production-ready. We can only hope AWS introduces a native Bun runtime in the near future! 🤞
If you discovered a more efficient method to deploy Bun in Lambda or if your performance results differ from mine, please share your experiences in the comments! 🙏
Top comments (0)