ALB vs NLB: Choosing the Right AWS Load Balancer for Your Web App

Picking the wrong load balancer is a silent architectural mistake — it works until it doesn't, costing you latency, money, or missing features at scale. Understanding where ALB and NLB operate in the OSI model is the fastest way to make the right call.

TL;DR — Quick Comparison

AttributeApplication Load Balancer (ALB)Network Load Balancer (NLB)
OSI LayerLayer 7 (Application)Layer 4 (Transport)
ProtocolHTTP, HTTPS, gRPC, WebSocketTCP, UDP, TLS
Routing LogicPath, host, header, query string, methodIP + Port only
Target TypesEC2 (instance), IP, LambdaEC2 (instance), IP
Static IPNo (DNS-based, IPs change)Yes (per-AZ Elastic IP)
TLS TerminationYes (ACM integration)Yes (pass-through or terminate)
WebSocketsNative supportTCP pass-through
Latency ProfileSlightly higher (L7 inspection)Ultra-low (no payload inspection)
Sticky SessionsCookie-based (duration or app-defined)Source IP-based
Use Case FitWeb apps, microservices, APIsGaming, IoT, financial systems, static IP requirements

The OSI Layer Difference — Why It Matters

The single most important distinction is where in the network stack each load balancer makes its routing decision.

  • ALB (Layer 7) reads the full HTTP request — URL path, hostname, headers, cookies — before deciding where to send traffic. It understands what is being requested.
  • NLB (Layer 4) routes based purely on IP address and TCP/UDP port. It never inspects the payload. It only knows where a packet is going, not what it contains.
Analogy: Think of ALB as a hotel concierge who reads your reservation details and directs you to the right room type (suite, standard, accessible). NLB is the building's elevator — it moves you to the correct floor based on the button you pressed, with zero knowledge of why you're going there.

Architecture: How Each Load Balancer Routes Traffic

graph LR Client(["Client Browser"]) subgraph ALB_Flow ["ALB - Layer 7 Routing"] ALB["ALB Listener HTTPS:443"] TG_API["Target Group API Service"] TG_Web["Target Group Web Frontend"] EC2_API["EC2 / ECS API Instances"] EC2_Web["EC2 / ECS Web Instances"] ALB -->|"path /api/*"| TG_API ALB -->|"path /*"| TG_Web TG_API --> EC2_API TG_Web --> EC2_Web end subgraph NLB_Flow ["NLB - Layer 4 Routing"] NLB["NLB Listener TCP:443"] TG_NLB["Target Group TCP Targets"] EC2_NLB["EC2 Instances"] NLB -->|"port match only"| TG_NLB TG_NLB --> EC2_NLB end Client --> ALB Client --> NLB
  1. Client Request: A browser or API client sends an HTTP/S request.
  2. ALB Listener: Inspects the full HTTP request at Layer 7.
  3. Content-Based Routing: ALB evaluates rules — path /api/* routes to the API target group; path / routes to the web frontend target group.
  4. Target Groups: Each target group contains EC2 instances, ECS tasks, or Lambda functions registered by instance ID or IP.
  5. NLB Listener: Receives raw TCP/UDP traffic and routes based on port number only — no payload inspection.
  6. NLB Targets: Forwards packets directly to registered EC2 instances or IP addresses with minimal processing overhead.

Deep Dive: ALB — Layer 7 Intelligence

Content-Based Routing Rules

ALB listener rules are evaluated in priority order. Each rule can match on:

  • Path pattern: /api/*, /images/*
  • Host header: api.example.com vs www.example.com
  • HTTP method: GET, POST, etc.
  • Query string: ?version=2
  • HTTP headers: Custom headers or User-Agent
  • Source IP (CIDR): Restrict access by IP range

ALB Listener Rule — Terraform Example

🔽 Click to expand — ALB Listener Rule (Terraform)
resource "aws_lb_listener_rule" "api_routing" {
  listener_arn = aws_lb_listener.https.arn
  priority     = 100

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

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

resource "aws_lb_listener_rule" "web_routing" {
  listener_arn = aws_lb_listener.https.arn
  priority     = 200

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

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

ALB Target Types

  • instance: Routes to EC2 instance by instance ID (uses primary private IP).
  • ip: Routes to any IP address — useful for ECS Fargate, on-premises targets via VPN/Direct Connect, or containers with multiple IPs.
  • lambda: Invokes a Lambda function directly — ALB serializes the HTTP request into a JSON event.

Deep Dive: NLB — Layer 4 Performance

When NLB Is the Right Tool

  • Static IP requirement: NLB assigns one Elastic IP per Availability Zone. Clients or firewall rules that require whitelisting a fixed IP need NLB.
  • Ultra-low latency: NLB operates without payload inspection, making it ideal for latency-sensitive workloads (gaming, HFT, real-time telemetry).
  • Non-HTTP protocols: UDP (DNS, syslog, SNMP), raw TCP (custom protocols, MQTT for IoT).
  • Preserving source IP: NLB preserves the client's source IP address natively (no X-Forwarded-For header needed).
  • PrivateLink: NLB is required as the backing load balancer for AWS PrivateLink service endpoints.

NLB Target Types

  • instance: Routes to EC2 instance by instance ID.
  • ip: Routes to any IP address within a VPC CIDR, a peered VPC, or on-premises via Direct Connect/VPN.

Sequence Diagram: Request Flow Comparison

sequenceDiagram participant C as Client participant ALB as ALB participant BE_ALB as Backend EC2 participant NLB as NLB participant BE_NLB as Backend EC2 Note over C,BE_ALB: ALB Flow - Connection Terminated at LB C->>ALB: TCP Handshake + HTTP Request ALB->>ALB: Inspect URL path and headers ALB->>BE_ALB: New TCP connection + forwarded request BE_ALB-->>ALB: HTTP Response ALB-->>C: HTTP Response Note over C,BE_NLB: NLB Flow - Connection Passed Through C->>NLB: TCP SYN packet NLB->>BE_NLB: Forward TCP SYN unchanged BE_NLB-->>C: TCP SYN-ACK direct or via NLB BE_NLB-->>C: Response data
  1. ALB flow: The load balancer terminates the TCP connection, reads the full HTTP request, evaluates routing rules, then opens a new connection to the selected backend. The backend sees the ALB's IP, not the client's (use X-Forwarded-For header to retrieve the original client IP).
  2. NLB flow: NLB does not terminate the connection. It performs connection-level load balancing and forwards packets directly. The backend sees the original client IP address natively.

Handling the "Fixed IP + HTTP Routing" Requirement

A common architectural challenge is needing both static IPs (for firewall whitelisting) and Layer 7 content-based routing. NLB alone provides static IPs but no HTTP routing. ALB provides HTTP routing but has dynamic IPs. Two supported patterns address this:

Pattern 1: AWS Global Accelerator + ALB

AWS Global Accelerator provides two static anycast IP addresses that front your ALB. Traffic enters the AWS global network at the nearest edge location and is routed to your ALB. The ALB retains full Layer 7 routing capability.

graph LR Client(["Client"]) FW["Corporate Firewall Whitelist Static IPs"] GA["AWS Global Accelerator 2 Static Anycast IPs"] ALB["Application Load Balancer Layer 7 Routing"] TG1["Target Group Service A"] TG2["Target Group Service B"] Client --> FW FW --> GA GA --> ALB ALB -->|"path /service-a/*"| TG1 ALB -->|"path /service-b/*"| TG2
  • Global Accelerator provides static IPs for firewall whitelisting.
  • ALB handles all content-based routing rules behind Global Accelerator.
  • This is the AWS-recommended pattern when static IPs + HTTP routing are both required.

Pattern 2: NLB with IP Targets Pointing to Backend Instances

If your requirement is purely static IP + TCP routing (no HTTP-level routing needed), register your backend EC2 or container IPs directly as NLB IP targets. This avoids any intermediary and keeps latency minimal.

Decision Flowchart: ALB or NLB?

graph TD Start(["Need a Load Balancer?"]) Q1{"HTTP or HTTPS traffic?"} Q2{"Need path or host routing?"} Q3{"Need WAF integration?"} Q4{"Need static fixed IPs?"} Q5{"Need UDP or non-HTTP TCP?"} Q6{"Need static IP + HTTP routing?"} ALB_REC["Use ALB"] NLB_REC["Use NLB"] GA_REC["Use Global Accelerator + ALB"] Start --> Q1 Q1 -->|"Yes"| Q2 Q1 -->|"No"| Q5 Q2 -->|"Yes"| ALB_REC Q2 -->|"No"| Q3 Q3 -->|"Yes"| ALB_REC Q3 -->|"No"| Q4 Q4 -->|"No"| ALB_REC Q4 -->|"Yes"| Q6 Q5 -->|"Yes"| NLB_REC Q5 -->|"No"| NLB_REC Q6 -->|"Yes"| GA_REC Q6 -->|"No"| NLB_REC

IAM & Security Considerations

  • ALB WAF Integration: ALB integrates natively with AWS WAF for Layer 7 protection (SQL injection, XSS, rate limiting). NLB does not support WAF.
  • Security Groups: ALB supports security groups. NLB does not support security groups on the load balancer itself — control access via target security groups or NACLs.
  • TLS: Both support TLS termination using ACM certificates. NLB additionally supports TLS pass-through (end-to-end encryption to the backend).
  • Least Privilege: When using Lambda as an ALB target, grant only lambda:InvokeFunction to the ALB service principal (elasticloadbalancing.amazonaws.com).
🔽 Click to expand — Lambda Resource Policy for ALB Target
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowALBInvoke",
      "Effect": "Allow",
      "Principal": {
        "Service": "elasticloadbalancing.amazonaws.com"
      },
      "Action": "lambda:InvokeFunction",
      "Resource": "arn:aws:lambda:us-east-1:123456789012:function:MyWebHandler",
      "Condition": {
        "StringEquals": {
          "aws:SourceArn": "arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/my-lambda-tg/1234567890abcdef"
        }
      }
    }
  ]
}

Scenario-Based Recommendation Summary

ScenarioRecommended ChoiceReason
Standard web app / REST APIALBPath/host-based routing, WAF, ACM
Microservices on ECS/EKSALBIP target type, gRPC support, per-service routing
Serverless backend (Lambda)ALBNative Lambda target type
Gaming / real-time UDPNLBUDP support, ultra-low latency
IoT / MQTTNLBTCP pass-through, source IP preservation
Static IP for firewall rulesNLBPer-AZ Elastic IP assignment
Static IP + HTTP routingGlobal Accelerator + ALBStatic anycast IPs with full L7 routing
AWS PrivateLink endpointNLBRequired by PrivateLink architecture
On-premises hybrid targetsALB or NLB (IP targets)Both support IP targets via Direct Connect/VPN

Glossary

TermDefinition
OSI Layer 7Application layer — understands HTTP, HTTPS, gRPC. Enables content-aware routing decisions.
OSI Layer 4Transport layer — understands TCP/UDP ports and IP addresses only. No payload inspection.
Target GroupA logical grouping of backend targets (EC2, IP, Lambda) that a load balancer routes traffic to.
Listener RuleA condition-action pair on an ALB listener that determines how incoming requests are routed.
AWS Global AcceleratorA networking service that provides static anycast IPs and routes traffic over the AWS global network to regional endpoints like ALBs.

Next Steps

Related Posts

Comments

Popular posts from this blog

EC2 No Internet Access in Custom VPC: Attaching an Internet Gateway and Fixing Route Tables

IAM User vs. IAM Role: Why Your EC2 Instance Should Never Use a User

EC2 SSH Connection Timeout: The Exact Security Group Rules You Need to Fix It