Compare and Troubleshoot ALBs and NLBs in AWS

Part One— ALB vs. NLB Performance Comparison

Eugene White
Slalom Build
5 min readJul 31, 2023

--

Does selecting a load balancer keep you up at night? How do you know which flavor of AWS Load Balancer suite is best for your specific use case? In this series of blog posts, I’ll discuss the architecture of the two most commonly used ELBs, the Application Load Balancer (ALB) and the Network Load Balancer (NLB). Understanding the differences between ALB and NLB will help you select which one is best for your needs and troubleshoot and design solutions for your customers.

I will break this comparison down across three blog posts:

In this blog post, we’ll look at performance differences between the two load balancers using practical examples with videos so you can see firsthand how to run tests and capture data.

First, let’s examine what ELBs are and why we need them. Load balancers have been used in traditional on-prem environments to distribute requests from clients, often on the public internet, to servers in the service provider’s private network. Their primary function is to ensure TCP sessions or layer 7 requests are evenly distributed to internal servers. Also, a load balancer can stop sending requests to servers if it detects the server is unhealthy, helping to make the user experience seamless. This same functionality is required by AWS to distribute requests across various services such as EC2 instances, ECS clusters, EKS clusters, and Lambda functions.

Just as your server capacity may need to expand and contract based on user demand, your ELB will need to do the same. AWS’s management of your ELB enables them to handle this “low value” scaling task while your developers stay focused on your application code.

Part One— ALB vs. NLB Performance Comparison

To gain a broad understanding of what each ELB can do in terms of performance, let’s run some simple performance tests on each one.

TCP Testing

I ran 50,000 curl requests to each ELB using a well-known curl performance script:

cat curl_script.txt
time_namelookup: %{time_namelookup}s\n
time_connect: %{time_connect}s\n
time_appconnect: %{time_appconnect}s\n
time_pretransfer: %{time_pretransfer}s\n
time_redirect: %{time_redirect}s\n
time_starttransfer: %{time_starttransfer}s\n
----------\n
time_total: %{time_total}s\n

This script gives a variety of information, but in our case, the important part is the time_total. You can see it can be used for testing dns (time_namelookup), tcp connection time (time_connect), ssl negotiation (time_appconnect), redirect, and download times.

The client I used was another EC2 instance in the same region, so I expected a generally low latency. For the ALB, I got these results (all units are ms):

Here are the results obtained from the NLB:

You can see that the NLB testing is more than four times faster, and its results are more reliable than the ALB; there’s a tighter standard deviation.

Pipelined requests testing

Testing where each request is pipelined into a single TCP connection is also essential. You can see an example of how request pipelining is done in the video I’ve linked to here.

In the below testing, fifty thousand requests were pipelined through a connection. This testing is much faster than the above TCP testing. Each output below is the result of running all 50,000 requests.

For the ALB:

For the NLB:

Here you can see the results shown above are much faster than running a new TCP connection per request. But these tests were done with very little response data from the server. I also ran some tests where the server responded with approximately 50KB per request.

Here are the results for the ALB.

And for the NLB:

We can see the results were very different this time. Why is the ALB so much slower in this case? The reason is due to the extra operations an ALB node must carry out. It must terminate an incoming TCP session, bring the payload data into memory, potentially route traffic based on this payload, then do a read operation in sending the data to its target. This write/read is not done in the case of the NLB. We can view the NLB as operating at the TCP layer only; it is essentially only rewriting IP-TCP headers.

The results above show the performance improvement that can be gained by using NLB, especially if your client/servers are doing large GET/PUT operations.

Are you ready to dive deeper into the architecture of each ELB? In my next post you’ll discover how the inherent operations of each ELB give rise to their performance differences whilst examining some of the abilities that an ALB has over an NLB and how those additional abilities can impact performance.

--

--