AWS Lambda has become a popular choice for serverless computing due to its scalability and cost-effectiveness. Developers often face a dilemma when choosing the right programming language for their Lambda functions, especially when performance and cost are critical. In this blog post, we’ll dive into a benchmarking comparison of AWS Lambda functions written in Node.js, Go, and Rust. Each Lambda function performs a simple task: parsing a JSON object with a single field and returning a greeting message.

The Task

The task for each Lambda function is straightforward:

  1. Parse the following JSON object:

    {
      "name": "Nebojsa"
    }
    
  2. Return the greeting: "Hello, Nebojsa"

While the task is simple, the performance implications can vary significantly depending on the language used. We will evaluate the performance based on key metrics such as execution duration, memory usage, and initialization time.

Benchmark Results

Let’s take a look at the performance metrics gathered during the benchmarking tests for each language.

Node.js Lambda

REPORT RequestId: 3f5846e1-9725-412c-9a5e-9d91d8804ccd	Duration: 51.90 ms	Billed Duration: 52 ms	Memory Size: 128 MB	Max Memory Used: 64 MB	Init Duration: 132.71 ms
REPORT RequestId: 2ab7ddf0-3296-46f1-a958-2761af3b45ce	Duration: 9.26 ms	Billed Duration: 10 ms	Memory Size: 128 MB	Max Memory Used: 64 MB
REPORT RequestId: 28b97c26-47ff-4383-9833-a294313d59a9	Duration: 2.05 ms	Billed Duration: 3 ms	Memory Size: 128 MB	Max Memory Used: 64 MB
REPORT RequestId: 1c0cd0af-5df1-443a-9f28-995a4737d868	Duration: 38.29 ms	Billed Duration: 39 ms	Memory Size: 128 MB	Max Memory Used: 64 MB
REPORT RequestId: 843fe901-5616-4583-95d3-585ecfe5590c	Duration: 2.28 ms	Billed Duration: 3 ms	Memory Size: 128 MB	Max Memory Used: 64 MB
  • Average Execution Duration: ~20 ms
  • Memory Usage: 64 MB
  • Initialization Duration: 132.71 ms (cold start)

Go Lambda

REPORT RequestId: a1eff6f3-2296-434d-ba4a-b3594c0cf50a	Duration: 1.65 ms	Billed Duration: 42 ms	Memory Size: 128 MB	Max Memory Used: 15 MB	Init Duration: 39.67 ms
REPORT RequestId: 469b5c9f-2b57-4d68-a1fc-715c3d0b081a	Duration: 1.20 ms	Billed Duration: 2 ms	Memory Size: 128 MB	Max Memory Used: 16 MB
REPORT RequestId: ad0fed4c-8e10-46d0-ac63-58cd69157dc2	Duration: 1.29 ms	Billed Duration: 2 ms	Memory Size: 128 MB	Max Memory Used: 16 MB
REPORT RequestId: 870e52a4-8402-43d9-98ba-7affd46dd212	Duration: 1.36 ms	Billed Duration: 2 ms	Memory Size: 128 MB	Max Memory Used: 16 MB
REPORT RequestId: 7a0a8363-2084-47c8-aa76-a3dc51c4eb45	Duration: 1.18 ms	Billed Duration: 2 ms	Memory Size: 128 MB	Max Memory Used: 16 MB
  • Average Execution Duration: ~1.34 ms
  • Memory Usage: 16 MB
  • Initialization Duration: 39.67 ms (cold start)

Rust Lambda

REPORT RequestId: 8a3e23c7-1dea-4149-9642-5e77ff4c907a	Duration: 1.63 ms	Billed Duration: 23 ms	Memory Size: 128 MB	Max Memory Used: 15 MB	Init Duration: 20.86 ms
REPORT RequestId: 039d7e26-1ab2-4478-895a-b4f9c4b1d0b3	Duration: 0.96 ms	Billed Duration: 1 ms	Memory Size: 128 MB	Max Memory Used: 15 MB
REPORT RequestId: ab87210a-290a-43ad-9a29-a319dbcfbb7d	Duration: 1.02 ms	Billed Duration: 2 ms	Memory Size: 128 MB	Max Memory Used: 16 MB
REPORT RequestId: ca7db28e-227c-484a-bc74-89d91f1f959a	Duration: 1.01 ms	Billed Duration: 2 ms	Memory Size: 128 MB	Max Memory Used: 15 MB
REPORT RequestId: 3c177e67-bedd-4b85-99d9-4c88653610ed	Duration: 0.96 ms	Billed Duration: 1 ms	Memory Size: 128 MB	Max Memory Used: 15 MB
  • Average Execution Duration: ~1.12 ms
  • Memory Usage: 15-16 MB
  • Initialization Duration: 20.86 ms (cold start)

Analysis

Execution Speed

Rust and Go significantly outperformed Node.js. Rust had an average execution time of about 1.12 ms, closely followed by Go at 1.34 ms. Node.js was slower, averaging around 20 ms. Rust’s performance makes it highly suitable for low-latency, performance-critical applications.

Memory Usage

Rust was the most memory-efficient, using 15-16 MB, slightly better than Go’s 16 MB and significantly better than Node.js’s 64 MB. This can be crucial in scenarios where optimizing for cost is essential.

Cold Start Time

Rust also had the fastest cold start time at 20.86 ms, making it ideal for applications that need to scale quickly during load spikes. Go was slower at 39.67 ms, and Node.js was the slowest at 132.71 ms.

Conclusion

Rust stands out as the top choice for AWS Lambda functions, delivering exceptional performance with the fastest execution times, lowest memory usage, and quickest cold starts. If your application demands high performance and efficiency, Rust should be your go-to language.

Go also performs admirably, making it a strong contender, especially if you’re looking for a balance between speed and ease of use. Node.js, while lagging in performance metrics, remains a viable option for developers who value its rich ecosystem and familiar JavaScript environment.

Ultimately, if maximizing Lambda performance is your priority, Rust offers the best results. For a more balanced approach with a slightly easier learning curve, Go is an excellent alternative. Node.js is best suited for scenarios where developer familiarity and ecosystem support outweigh the need for raw speed and efficiency.