How to use LLRT on AWS Lambda with AWS CDK & Lambda Layers

Updated on
llrt lambda clock cover

LLRT is Low Latency Runtime written in Rust. LLRT is made for AWS Lambda. It can significantly reduce your Lambda cold start duration and also save your cost by 2x.

Warning

For now, LLRT is an experimental package. It is subject to change and intended only for testing purposes.

You can find out if LLRT supports the node libraries you use from LLRT GitHub docs.

Many of your favourite NodeJS libraries may not work with LLRT, so check if a library is compatible with LLRT APIs for AWS Lambda.

You can check the compatibility matrix on the LLRT repo.

AWS SDK v3 Optimization

AWS team has optimized and bundled many AWS SDKs in the LLRT runtime itself. So you don’t need to bundle it with your JavaScript code.

Supported AWS SDKs

Important

When bundling your code make sure to exclude these dependencies

Bundled AWS SDK packages
@aws-sdk/client-dynamodb
@aws-sdk/lib-dynamodb
@aws-sdk/client-kms
@aws-sdk/client-lambda
@aws-sdk/client-s3
@aws-sdk/client-secrets-manager
@aws-sdk/client-ses
@aws-sdk/client-sns
@aws-sdk/client-sqs
@aws-sdk/client-sts
@aws-sdk/client-ssm
@aws-sdk/client-cloudwatch-logs
@aws-sdk/client-cloudwatch-events
@aws-sdk/client-eventbridge
@aws-sdk/client-sfn
@aws-sdk/client-xray
@aws-sdk/client-cognito-identity
@aws-sdk/util-dynamodb
@aws-sdk/credential-providers
@smithy

Bundling your TypeScript / JavaScript Code for LLRT

We can’t use ES2023 and TypeScript with LLRT, so we need to bundle our code to JavaScript using ESBuild.

Make sure to install esbuild globally with your package manager to use esbuild via CLI:

pnpm i -g esbuild

ESBuild command for bundling Lambda code

esbuild index.js --platform=node --target=es2023 --format=esm --bundle --minify --external:@aws-sdk --external:@smithy --external:uuid

How to use LLRT with AWS Lambda

Option 1: Create LLRT function with AWS CDK

Tip

Why CDK? AWS CDK (Cloud Development Kit) is the easiest and faster way to get your AWS Lambda code up and running

  1. Create a AWS CDK project in TypeScript
  2. Install cdk-lambda-llrt construct
  3. Create a new Lambda function with LlrtFunction constructor
  4. Deploy the changes with cdk deploy
import { LlrtFunction } from "cdk-lambda-llrt";

const handler = new LlrtFunction(this, "Handler", {
  entry: "lambda/index.ts",
});

Check out the detailed example on Using LLRT on AWS Lambda with CDK below.

Option 2: Manually bundling LLRT binary with code

  1. Create an AWS Lambda Function with runtime on Amazon Linux 2023
  2. Download and extract the Lambda LLRT bootstrap file from GitHub release.
  3. Bundle your TypeScript / JavaScript code with ESBuild.
  4. Zip your JavaScript code and LLRT bootstrap together.
  5. Use AWS Console or AWS CLI to update your Lambda function code.

Option 3: Using a LLRT Lambda layer

Lambda layers is one of the common ways to run custom binaries in your Lambda function.

Warning

Layers aren’t the recommended way for using LLRT. Downloading a layer on every cold start adds some extra time.

>> Skip to the next section >>

Create LLRT Lambda Layer

  1. Download the LLRT bootstrap zip for Lambda from GitHub release
  2. Go to AWS Lambda layer console to create a new layer
  3. Pick your architecture (arm64)
  4. Upload Lambda LLRT zip file
  5. Select runtime to be Amazon Linux 2023
  6. Click on Create to finish Layer creation

LLRT create Lambda layer page

Use LLRT Lambda layer in your Lambda function

Now we’ve created LLRT layer for arm64, we can use it in our Lambda function.

Step 1. Create an AWS Lambda Function with runtime on Amazon Linux 2023

Lambda console screenshot for creating LLRT function

Step 2. Attach the Layer

LLRT layer attachment on Lambda function

Step 3. Write your JavaScript code in hello.mjs

To test out we can simply return a string from handler function:

export const handler = () => {
  return "Hello from LearnAWS.io";
};

LLRT hello function code Once you’re done, hit Deploy.

Tip

If you want to change your Lambda file and function name you can update it in the handler.

Testing the Function

To test you can click on the Test button and create simple test event. Click on Test button again to run the test.

You will get this in response:

"Hello from LearnAWS.io"

And in the Function logs you will see the Billed Duration and Init Duration which is way less than NodeJS:

START RequestId: 0f79bdd8-cf93-43a8-aba2-836daa12a3f5
Version: $LATEST
END RequestId: 0f79bdd8-cf93-43a8-aba2-836daa12a3f5
REPORT RequestId: 0f79bdd8-cf93-43a8-aba2-836daa12a3f5
Duration: 1.55 ms
Billed Duration: 35 ms
Memory Size: 128 MB
Max Memory Used: 21 MB
Init Duration: 32.46 ms

Here is the screenshot of Lambda console which shows the test results and logs from CloudWatch:

LLRT layer Lambda Console demo results

That’s it. Really.

Warning

Even though LLRT supports ES2020 it’s NOT a drop in replacement for Node.js. Consult Compatibility matrix and API for more details. All dependencies should be bundled for a browser platform and mark included @aws-sdk packages as external.

Using LLRT on AWS Lambda with CDK

Create a CDK project wtih npx cdk init app --language typescript.

Tip

Don’t know how to use AWS CDK? Follow this step-by-step article to create a TypeScript CDK project

Once you’ve created a CDK project update the stack code with the LLRT and NodeJS function:

import { NodejsFunction, OutputFormat } from "aws-cdk-lib/aws-lambda-nodejs";
import { CfnOutput, Stack, StackProps } from "aws-cdk-lib";
import { PolicyStatement } from "aws-cdk-lib/aws-iam";
import { LlrtFunction } from "cdk-lambda-llrt";
import { Construct } from "constructs";
import {
  Architecture,
  FunctionUrlAuthType,
  Runtime,
} from "aws-cdk-lib/aws-lambda";

export class LambdaLlrtStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    const llrtFn = new LlrtFunction(this, "llrt-demo-fn", {
      entry: "lambda/index.ts",
      architecture: Architecture.ARM_64,
    });

    const s3Policy = new PolicyStatement({
      actions: ["s3:ListAllMyBuckets"],
      resources: ["*"],
    });

    llrtFn.addToRolePolicy(s3Policy);

    const llrtFnUrl = llrtFn.addFunctionUrl({
      authType: FunctionUrlAuthType.NONE,
    });

    new CfnOutput(this, "llrt-url", { value: llrtFnUrl.url });
  }
}

What does the CDK code do?

The CDK code does the following:

  • Creates an LLRT Lambda function with arm64 architechture.
  • Creates an S3 policy with ListAllMyBuckets action
  • Attaches S3 policy to the Lambda function
  • Enables function URL with public access
  • Logs the LLRT function URL

Lambda Function Code to List S3 buckets

Update your lambda/index.ts code to list the S3 buckets:

import { APIGatewayProxyHandlerV2 } from "aws-lambda";
import { ListBucketsCommand, S3Client } from "@aws-sdk/client-s3";

const s3 = new S3Client({});

export const handler: APIGatewayProxyHandlerV2 = async (event, context) => {
  const list = await s3.send(new ListBucketsCommand({}));
  const liArr = list.Buckets?.map((buck) => `<li>${buck.Name}</li>`);
  const html = `<ul>${liArr?.join("\n")}</ul>`;
  return {
    body: html,
    headers: { "Content-Type": "text/html" },
    statusCode: 200,
  };
};

Deploy the changes with cdk deploy.

You’ll have both LLRT and NodeJS function URL in the output:


 ✅  LlrtStack

✨  Deployment time: 50.24s

Outputs:
LambdaLlrtStack.llrturl = https://xxxx.lambda-url.us-east-1.on.aws/

Stack ARN:
arn:aws:cloudformation:us-east-1:xxxx:stack/LambdaLlrtStack/xxxx

✨  Total time: 53.41s

Testing LLRT Lambda Function

You can simply visit or cURL the function URL to test the response.

Browser screenshot showing list of buckets returned from AWS Lambda LLRT function URL and rendered as an HTML

CloudWatch Log for LLRT Lambda Function

You can go to the CloudWatch log group of the LLRT Lambda function and check how much duration it has taken for cold start and billed duration.

See pointers 1 and 2 in the screenshot below:

| INIT_START Runtime Version: provided:al2023.v12 Runtime Version ARN: arn:aws:lambda:us-east-1::runtime:136ed310b999b334fac0d4a087dd5c3d4f95efe17b434ba3c1eefb429c00f150 |
| START RequestId: b91fe80f-2bd1-4905-966d-3162af59a06b Version: $LATEST                                                                                                  |
| END RequestId: b91fe80f-2bd1-4905-966d-3162af59a06b                                                                                                                     |
| REPORT RequestId: b91fe80f-2bd1-4905-966d-3162af59a06b Duration: 102.84 ms Billed Duration: 150 ms Memory Size: 128 MB Max Memory Used: 21 MB Init Duration: 46.22 ms   |

AWS Cloudwatch log group showing Lambda Init duration of 46ms and billed duration of only 150ms

Tip

Interested in knowing the benchmarks of NodeJS vs LLRT? Check out our detailed benchmaks on LLRT vs NodeJS article.

I hope you enjoyed experimenting with AWS LLRT, till then, see ya!

Don’t forget to share this article on your socials ;)

Source code for CDK project can be found on LearnAWS LLRT Github repo.


Hills 🏔 and Skills, What's Common?

They both need you to be on top.

You will get lifetime access with:

All yours, just at:

$149

Just type and your search result will magically appear here