🥇 The Best Serverless Framework in 2023: A Data-Driven Showdown for AWS Projects
Tags: serverless, aws, webdev, javascript
Published: 2023-09-22 15:12:26


---
published: true
title: '🥇 The Best Serverless Framework in 2023: A Data-Driven Showdown for AWS Projects'
description: 'Learn which is the best framework to develop serverless apps on AWS in 2023'
tags: serverless, aws, webdev, javascript
---

## 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:

> ```bash
> aws sts get-caller-identity
> ```

> If you are not logged in, run the command below:

> ```bash
> 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](https://github.com/oven-sh/bun/tree/main/packages/bun-lambda) to add the layer to your AWS account.

When executing bun publish-layer, ensure you choose the `aarch64` architecture ⚡!

```bash
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](https://sst.dev/guide.html) 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](https://dev.to/slsbytheodo/the-best-serverless-framework-in-2023-a-data-driven-showdown-for-aws-projects-1p3h)

Proceed with the steps in SST's [standalone get started section](https://docs.sst.dev/start/standalone).

In essence, you'll execute:

```bash
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`

```json
{
  "compilerOptions": {
    "types": ["bun-types"] // add Bun global
  }
}
```

Then, draft a basic lambda handler leveraging the `Bun.password` API (this ensures Bun is operational!):

```typescript
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:

```typescript
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:

```json
    "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.

```json
{
  "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!

## Conclusion & Caveats 🥲

Using the custom Bun Layer comes at a cost: ~500ms cold start time. 🥶

Moreover, after conducting load tests on computationally intensive tasks (like calculating Fibonacci sequences), I observed performance to be nearly 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! 🤞

I hope you found this article insightful! If you discover a more efficient method to deploy Bun in Lambda or if your performance results differ from mine, please share your experiences in the comments! 🙏