Lambda optimization tip – enable HTTP keep-alive
Tags: aws, awslambda, serverless, cloud
Published: 2019-04-19 20:39:36

---
title: Lambda optimization tip – enable HTTP keep-alive
published: true
description: How to improve the performance of Node.js Lambda functions with a simple trick.
tags: aws, awslambda, serverless, cloud
canonical_url: https://theburningmonk.com/2019/02/lambda-optimization-tip-enable-http-keep-alive/
---

I recently watched an [excellent talk](https://vimeo.com/287511222?fbclid=IwAR31W61fC-MJcXiPdT4ywMKX-ccKiAzviQogcOaivyGpPzcj5vY16A6obCw) by Matt Lavin on optimization tips for Lambda and saw a slide on making DynamoDB use HTTP keep-alive. It reminded me of a conversation I had with Sebastian Cohnen, so I set out to test the effect this simple optimization has.

![](https://theburningmonk.com/wp-content/uploads/2019/02/img_5c55f659697f8-1024x572.png)

## What is it all about?

As it turns out, Node.js’s default HTTP agent doesn’t use keep-alive and therefore every request would incur the cost of setting up a new TCP connection. This is clearly inefficient, as you need to perform a [three-way handshake](https://www.inetdaemon.com/tutorials/internet/tcp/3-way_handshake.shtml) to establish a TCP connection. For operations that are short-lived (such as DynamoDB operations, which typically complete within a single digit ms) the latency overhead of establishing the TCP connection might be greater than the operation itself.

With the Node.js AWS SDK, you can [override the HTTP agent](https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/node-configuring-maxsockets.html) to use for ALL clients with just a few lines of code. You can also override the settings for individual clients too.

![](https://theburningmonk.com/wp-content/uploads/2019/02/img_5c55fd4aa035f-1024x469.png)

## The tests

To test the effect of enabling HTTP keep-alive, I set up a simple Lambda function behind API Gateway. Essentially this function puts an item into a DynamoDB Table, and that’s it.

![](https://theburningmonk.com/wp-content/uploads/2019/02/img_5c55fdfa000a9-1024x719.png)

For this experiment, I wanted to see how well the HTTP keep-alive fared across multiple invocations and how much of a difference do we see with this simple change.

## The results

Without HTTP keep-alive, the DynamoDB operation averaged around **33ms**.

![](https://theburningmonk.com/wp-content/uploads/2019/02/img_5c55fad78932d-1024x554.png)

With HTTP keep-alive, that average drops to around **10ms**.

![](https://theburningmonk.com/wp-content/uploads/2019/02/img_5c55fb9cc34b1-1024x558.png)

As we suspected, the overhead (33ms-10ms = 23ms) was greater than the cost of the operation itself. The experiment shows that the connection is reused across multiple invocations just fine. With a very simple change, we were able to improve execution time by ~20ms, or to put it more impressively, reduce response time by 70%. That’s good return on investment in my book, but the difference is still not noticeable to the human eye.

But what if we scale this to 10 sequential DynamoDB operations in a single function?

With HTTP keep-alive, the function’s execution time averages around **60ms**.

![](https://theburningmonk.com/wp-content/uploads/2019/02/img_5c56060317f66-1024x525.png)

Without HTTP keep-alive, the average execution time rises to **180ms**.

![](https://theburningmonk.com/wp-content/uploads/2019/02/img_5c560663ab674-1024x554.png)

As I curl the endpoint, the difference of **120ms** is definitely noticeable. This difference can start to impact user experience, and as Amazon found 10 years ago, [adding 100ms of latency can reduce sales by as much as 1%](https://blog.gigaspaces.com/amazon-found-every-100ms-of-latency-cost-them-1-in-sales/).