AWS Lambda Javascript Low Latency Runtime(LLRT) Benchmark — Part 2

Oleksandr Hanhaliuk
4 min readMar 2, 2024

In Part 1, we made a benchmark comparing Node.js 20 with the new AWS LLRT using the Fibonacci sequence and simple HTTP request. You can read how to pack runtime into lambda and how to run tests.

In this article, we will go deeper into more usual use cases for AWS Lambda:

  • Dynamo DB requests
  • S3 bucket operations

Preparing for benchmark

We will write lambda, which will accept events with type: “dynamo” or “s3” and do operations either with DynamoDB or S3 bucket.

Before that, I will prepare a DynamoDB table with seed data and an S3 bucket before that.

Writing lambda code

First, we write a simple function for Dynamo DB getItem/putItem/deleteItem operations


async function benchmarkDynamo() {
const client = new DynamoDB({})

const randomUniqueId = Math.random().toString(36).substring(7)

const tableName = process.env.TABLE_NAME || 'test-table'

console.log('randomUniqueId', randomUniqueId)

const event = {
// ... random data
uniqueId: randomUniqueId,
}
console.log('Dynamo event', { event })

// put item
const putItemParams = {
TableName: tableName,
Item: marshall(event),
}
await client.putItem(putItemParams)
console.log('Item added to Dynamo')
// get item
const getItemParams = {
TableName: tableName,
Key: {
uniqueId: { S: randomUniqueId },
},
}
const res = await client.getItem(getItemParams)
console.log('Item fetched from Dynamo:', res.Item)

// delete item

const deleteItemParams = {
TableName: tableName,
Key: {
uniqueId: { S: randomUniqueId },
},
}
await client.deleteItem(deleteItemParams)
console.log('Item deleted from Dynamo')
return 'Dynamo benchmark done'
}

The second function will be for operations with an S3 bucket


async function benchmarkS3Bucket() {
// fetch url
const s3Client = new S3Client({
region: "us-east-1",
})

const imageUrl = 'https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png'
const bucketName = process.env.BUCKET_NAME || 'test-bucket'
const key = '/test-key.png'
const putItemParams = {
Bucket: bucketName,
Key: key,
Body: imageUrl,
}
await s3Client.send(new PutObjectCommand(putItemParams))
console.log('Image uploaded to S3')

const getItemResult = await s3Client.send(new GetObjectCommand({ Bucket: bucketName, Key: key }))

console.log('Image fetched from S3:', getItemResult)


const deleteItemParams = {
Bucket: bucketName,
Key: key,
}
await s3Client.send(new DeleteObjectCommand(deleteItemParams))
console.log('Image deleted from S3')


return 'S3 benchmark done'
}

And finally handler code which will accept event with type s3 or dynamo

import { DynamoDB } from '@aws-sdk/client-dynamodb'
import { DeleteObjectCommand, GetObjectCommand, PutObjectCommand, S3Client } from '@aws-sdk/client-s3'
import { marshall } from '@aws-sdk/util-dynamodb'

let isLambdaWarm = false

export async function handler(event: any) {
console.log('Starting function...:', { isLambdaWarm })
if (!isLambdaWarm) {
isLambdaWarm = true
}

const eventType = event.type
const startTime = Date.now()

let result
switch (eventType) {
case 'dynamo':
result = await benchmarkDynamo()
break
case 's3':
result = await benchmarkS3Bucket()
break
default:
result = 'Event type not supported'
break
}
const endTime = Date.now()

return {
result,
startTime,
endTime,
duration: endTime - startTime,
}
}

Analyzing results

After multiple runs of Lambda with Node.js 20 runtime and Lambda with LLRT runtime, both warm and cold, we can analyze the results

Dynamo DB operations comparison

Here is the average lambda total execution time during warm and cold starts during Dynamo DB operations

As we can see AWS Low Latency Runtime shows better results than Node.js especially on Warm start. But the difference is not so crucial.

S3 bucket operations comparison

Here is the average lambda total execution time during warm and cold starts during S3 bucket get object, put object and delete object operations

For the S3 bucket operations we can also see similar picture.

Summary

After running our tests a bunch of times to see how both the LLRT and Node.js 20 runtimes perform, here’s the scoop:

  • DynamoDB Operations: LLRT is somewhat faster than Node.js 20, especially when the function is already warmed up. Though, to be honest, the difference isn’t mind-blowing. It’s better, but not by a huge margin.
  • S3 Bucket Operations: Similar story here. LLRT shows some speed improvements over Node.js 20, which is pretty neat. Again, it’s good but doesn’t completely change the game.

So, what’s the takeaway from all this? Well, it seems like AWS Lambda’s new LLRT has a bit of an edge over the old Node.js 20 runtime for tasks involving DynamoDB and S3 buckets, especially when things are warmed up. This little experiment gives us a clearer picture of when it might be a good idea to switch over to LLRT. I will still use Node.js runtime since I like simple CDK class called Nodejs Function. But I hope AWS team will incorporate this runtime as default one. Lets see.

--

--