Why ELB Has Three Types - The Design Rationale Behind ALB, NLB, and CLB
Explore why ALB, NLB, and CLB (Classic) coexist rather than being unified into a single service, examining OSI model layers, performance characteristics, and historical context.
Classic Load Balancer - The Origin of ELB
Elastic Load Balancing (now Classic Load Balancer), launched in 2009, was AWS's first load balancer service. CLB was designed as a general-purpose load balancer capable of handling both L4 (TCP) and L7 (HTTP/HTTPS) traffic. However, this "do everything" design later became problematic. L4 and L7 load balancing are fundamentally different processes. L4 routes based solely on source/destination IP addresses and port numbers, without inspecting packet contents (HTTP headers or body). L7 analyzes HTTP request content (URL paths, host headers, cookies, etc.) for routing decisions. Providing both in a single service creates a tradeoff where L4 processing is affected by L7 overhead, and L7 feature expansion impacts L4 stability. Due to these constraints, CLB could not implement advanced L7 routing such as path-based or host-based routing.
The Birth of ALB - A Design Specialized for L7
Application Load Balancer (ALB), launched in 2016, is a load balancer fully specialized for L7 (HTTP/HTTPS). It enabled capabilities that were impossible with CLB: path-based routing (/api/* to API servers, /static/* to static file servers), host-based routing (api.example.com and www.example.com to different target groups), and routing based on HTTP headers or cookies. ALB's L7 specialization enabled critical features like native WebSocket support and HTTP/2 support, neither of which CLB could properly handle. ALB has continued to add application-layer features including AWS WAF integration, built-in Cognito authentication, and the ability to directly invoke Lambda functions as targets. These features are only possible because ALB can parse HTTP requests - they are fundamentally impossible with an L4 load balancer. ALB pricing is calculated using LCU (Load Balancer Capacity Units), determined by the maximum of four metrics: new connections, active connections, processed data, and rule evaluations.
The Birth of NLB - Pursuing Extreme L4 Performance
Network Load Balancer (NLB), launched in 2017, is specialized for L4 (TCP/UDP/TLS) and pursues extreme performance. NLB can handle millions of requests per second with latency in the tens of microseconds - orders of magnitude lower than ALB's millisecond-range latency. This performance difference stems from NLB not inspecting packet contents at all. NLB makes routing decisions at the flow level (source IP + port, destination IP + port combination) and forwards subsequent packets to the same target. With no HTTP header parsing, cookie reading, or URL path evaluation, overhead is extremely minimal. Another key NLB feature is static IP address support. ALB IP addresses change dynamically, so it can only be accessed via DNS name. NLB has fixed IP addresses per AZ (with Elastic IP assignment available), making it registrable in firewall IP whitelists. NLB is essential for environments like financial institutions and telecommunications providers that require fixed destination IP addresses.
Why Not Unify Into One Service
The question "why not unify ALB and NLB into one service" is natural, but the reasons for keeping them separate are technically clear. L4 and L7 load balancing have fundamentally different processing pipelines. L7 receives all packets, reassembles them as HTTP requests, parses headers, evaluates routing rules, optionally rewrites headers, then forwards to targets. This processing consumes memory and CPU. L4 examines only packet headers (IP + TCP/UDP) to determine the forwarding destination without touching packet contents. In extreme cases, NLB can bypass the kernel network stack and forward packets at the NIC (Network Interface Card) level. Unifying these two processes into one service would cause L4 performance to degrade, dragged down by the L7 processing pipeline. AWS's design philosophy of "purpose-built services" separates and optimizes functionality to avoid exactly this kind of tradeoff.
Selection Criteria
The choice among the three ELB types is determined by workload characteristics. Choose ALB for HTTP/HTTPS traffic requiring path-based or host-based routing. Most web applications, REST APIs, and microservices are best served by ALB. Choose NLB for TCP/UDP traffic requiring extreme performance or static IPs. Game servers, IoT device connections, financial trading systems, and gRPC (HTTP/2-based but sufficient at L4) are well-suited for NLB. CLB should not be used for new deployments. AWS recommends migrating from CLB to ALB or NLB, and there are virtually no features exclusive to CLB. The only exception was environments using EC2-Classic networking (retired in 2022). ALB and NLB can also be combined. Placing an ALB behind an NLB provides both NLB's static IPs and ALB's L7 routing. Since AWS PrivateLink requires NLB, this configuration is used when you need to expose a service via PrivateLink while also requiring L7 routing. To systematically learn load balancer design patterns, specialized books (Amazon) are a great reference.