bigonotes
CloudNetworking

Elastic Load Balancing: ALB, NLB and CLB

How AWS load balancers use listeners, rules and target groups, and how to choose between ALB, NLB and the older CLB.

8 min readLast updated

Elastic Load Balancing (ELB) is AWS's managed load balancer service. It gives clients one stable DNS name, spreads their traffic over healthy targets in several Availability Zones, and scales itself as traffic grows. You will meet it in front of almost every web service on AWS. This note covers the parts of an AWS load balancer and how the three main types differ. For the general ideas (layer 4 vs layer 7, algorithms, health checks), see Load Balancing.

The building blocks#

The current load balancers (ALB and NLB) share one model. The Classic Load Balancer is simpler and is covered at the end.

Part What it does
Load balancer Runs nodes in the subnets you choose (one per AZ) and has one DNS name
Listener Waits for connections on one protocol and port, such as HTTPS on 443
Rule A condition plus an action, checked in priority order
Target group A set of targets plus the protocol, port and health check to use
Target An EC2 instance, an IP address, a Lambda function (ALB) or an ALB (NLB)

The table gives the shape. These details are the ones that matter in practice:

  • Each listener has a default rule. It runs when no other rule matches, so every request has somewhere to go.
  • One target can belong to several target groups. An instance can serve both /api traffic on port 8080 and web traffic on port 80.
  • A target group can list the same instance on several ports. This is how containers with dynamic host ports (for example on Amazon ECS) sit behind one load balancer.
  • Enable at least two AZs. If one AZ fails, the load balancer keeps sending traffic to targets in the others.

Health checks#

Spreading traffic over healthy targets only works if the load balancer can tell which ones are healthy. Each target group has its own health check: the load balancer sends a probe to each target at a set interval. After a set number of failures in a row, it marks the target unhealthy and stops sending it new requests. After enough passes, the target returns to service.

  • An ALB checks with HTTP or HTTPS, on a path you choose such as /health, and expects a success code.
  • An NLB can check with TCP, HTTP or HTTPS.
  • If every target in a group is unhealthy, the load balancer "fails open" and sends traffic to all of them. It assumes the health check is wrong rather than the whole fleet.
  • When a target is removed, deregistration delay (connection draining) lets in-flight requests finish before the target stops getting traffic. A long delay slows deploys. A short one can cut off slow requests.

Internet-facing vs internal#

Before choosing a type, you make one decision that applies to all of them: who can reach the load balancer. You pick this scheme when you create it, and you cannot change it later.

Internet-facing Internal
Node IPs Public Private only
DNS name resolves to Public IPs Private IPs
Who can reach it Any client on the internet Clients in the VPC or connected networks (peering, VPN, Direct Connect)
Subnets Public subnets Usually private subnets
Typical use Public website or API Service-to-service calls inside the VPC

A common design chains them. An internet-facing ALB takes user traffic and sends it to a web tier. The web tier calls an internal load balancer in front of a private API tier. The targets of an internet-facing load balancer can stay in private subnets; only the load balancer nodes need public IPs.

Application Load Balancer (ALB)#

With the shared model in place, here's how each type uses it, starting with the one you'll use most. The ALB works at layer 7. It ends the client's HTTP connection, reads the request, and picks a target group from its rules.

  • Protocols: HTTP and HTTPS, including HTTP/2. It supports WebSocket and gRPC.
  • Rule conditions: host header, path, HTTP header, HTTP method, query string and source IP.
  • Rule actions: forward (to one target group, or split by weight across several), redirect, return a fixed response, or authenticate the user first.
  • TLS termination: it holds the certificate, usually from AWS Certificate Manager (ACM), which renews it for you.
  • Client IP: the target sees the ALB's address as the source. The client's IP arrives in the X-Forwarded-For header.
  • Sticky sessions are set per target group, using a cookie.
  • It integrates with AWS WAF to block common web attacks.
  • It has no fixed IP addresses. Its node IPs change, so clients must use its DNS name.

Worked example: path-based routing#

To see the rules from the building blocks in action, take an online shop that runs three services behind one ALB on shop.example.com. The HTTPS listener on port 443 has these rules:

Priority Condition Action
1 Path is /api/* Forward to api-tg (instances, port 8080)
2 Path is /static/* Forward to static-tg (instances, port 80)
3 Host is admin.example.com Forward to admin-tg, only from office IPs
Default Anything else Forward to web-tg (instances, port 80)

The listener checks rules in priority order. Here is how three requests flow:

  1. GET /api/users reaches the listener. Rule 1 matches. The ALB picks a healthy target in api-tg and forwards the request to it on port 8080.
  2. GET /static/logo.png misses rule 1 and matches rule 2. It goes to static-tg.
  3. GET /dashboard matches no numbered rule. The default rule sends it to web-tg.

Each target group has its own health check. For example, api-tg can check /api/health often, while static-tg checks / less often. The target sends its response back through the ALB to the client.

In infrastructure-as-code, rule 1 from the table looks like this in Terraform:

resource "aws_lb_listener_rule" "api" {
  listener_arn = aws_lb_listener.https.arn
  priority     = 1

  condition {
    path_pattern {
      values = ["/api/*"]
    }
  }

  action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.api.arn
  }
}

Network Load Balancer (NLB)#

The ALB's strength is reading requests. The NLB trades that away for speed. It works at layer 4. It forwards TCP, UDP and TLS connections without reading the payload. This keeps latency low and lets it handle very large traffic volumes and sudden spikes.

  • Static IPs: an NLB has one static IP per AZ. You can also bring your own Elastic IP for each AZ. This is the main reason to pick an NLB when a client or partner must allow-list fixed addresses.
  • Client IP: for instance targets, the target sees the client's real source IP, with no header needed.
  • Stickiness: an NLB supports sticky sessions based on the source IP. Requests from one client address go to the same target.
  • TLS: it can end TLS for you, or pass encrypted traffic through to the targets untouched.
  • Long-lived connections: it suits connections that stay open for a long time, such as WebSockets over TCP, game sessions and IoT devices.
  • Targets: instances, IP addresses, or an ALB. Putting an ALB behind an NLB gives you static IPs plus layer 7 routing.
  • It has no content-based rules. A listener forwards to one target group.

Classic Load Balancer (CLB)#

The last type is the one the building blocks section set aside. The CLB is the previous-generation load balancer. AWS recommends ALB or NLB for new work and offers a migration path. You may still find CLBs in older accounts.

  • It handles HTTP, HTTPS, TCP and SSL listeners, with basic layer 4 and layer 7 behavior.
  • It has no target groups. You register instances with the load balancer directly.
  • It has no host-based or path-based routing rules.
  • It supports health checks, TLS offload, cookie-based sticky sessions, access logs and CloudWatch metrics.

Choosing a load balancer#

With all three types covered, the table compares them side by side. Start from what the clients need, then pick the type.

Need ALB NLB CLB
Layer 7 4 4 and 7 (basic)
Route by path, host or header ✓ ✗ ✗
WebSocket and gRPC ✓ TCP pass-through ✗
UDP ✗ ✓ ✗
Static IP per AZ ✗ ✓ ✗
Client IP visible to target Header Directly Header
Sticky sessions Cookie Source IP Cookie
Status Current Current Previous generation

Default to an ALB for HTTP services. Choose an NLB for non-HTTP protocols, UDP, extreme throughput, or fixed IPs. Use neither for traffic across Regions; a load balancer serves one Region. For multi-Region setups, use Route 53 routing policies or AWS Global Accelerator in front.

Common problems#

Most load balancer issues show up as one of a few symptoms. Each maps back to a setting covered above.

Symptom Likely cause Fix
Healthy targets marked unhealthy Wrong health check path, port or security group Test the path; allow the load balancer's security group on the target
WebSocket connections drop Idle timeout reached Raise the ALB idle timeout, or send keep-alive pings
A few targets overloaded Sticky sessions pin heavy users Move session state to a shared store and turn stickiness off
Uneven load across AZs Unequal target counts per AZ Balance targets per AZ, or check cross-zone load balancing
HTTPS errors Expired or wrong certificate Use ACM-managed certificates

Key takeaways#

  • A listener receives traffic, rules choose an action, and target groups hold the targets and their health check.
  • Internet-facing load balancers have public node IPs; internal ones resolve to private IPs. The targets can stay private in both cases.
  • ALB is layer 7: path, host and header routing, WebSocket, gRPC, cookie stickiness, client IP in X-Forwarded-For.
  • NLB is layer 4: TCP, UDP and TLS, a static IP per AZ, client IP preserved, source-IP stickiness.
  • CLB is previous generation. Use ALB or NLB for anything new.
Revision notes · 2 min

Core idea#

ELB gives clients one DNS name and spreads traffic over healthy targets in several AZs. Listeners receive traffic, rules choose an action, and target groups hold the targets.

Key points#

  • A listener has one protocol and port. Its default rule catches unmatched requests.
  • A target group sets the protocol, port and health check for its targets.
  • One target can sit in several target groups, or on several ports.
  • If every target is unhealthy, the load balancer fails open to all of them.
  • Deregistration delay lets in-flight requests finish.
  • Internet-facing nodes have public IPs. Internal ones resolve to private IPs.
  • Targets can stay in private subnets in both cases.

ALB vs NLB vs CLB#

ALB NLB CLB
Layer 7 4 4 and 7 (basic)
Routing Path, host, header Port only Port only
Extras WebSocket, gRPC, WAF UDP, TLS pass-through TLS offload
Static IP ✗ One per AZ, Elastic IP option ✗
Client IP X-Forwarded-For Preserved Header
Stickiness Cookie Source IP Cookie
  • CLB is previous generation. Use ALB or NLB for new work.

Pitfalls#

  • A wrong health check path or security group marks healthy targets unhealthy.
  • Idle timeouts drop WebSockets. Raise the timeout or send pings.
  • Sticky sessions overload some targets. Move sessions to a shared store.
  • A load balancer serves one Region. Use Route 53 or Global Accelerator across Regions.

Say it in an interview#

  • "ALB for HTTP with path routing; NLB for TCP, UDP or fixed IPs."
  • "Internet-facing ALB, private targets in two AZs, per-group health checks."

Found a mistake? Email ask@bigonotes.com

Further reading#