AWS Load Balancers: ALB vs NLB vs CLB Complete Guide (2026)

AWS offers three active load balancer types: Application Load Balancer (ALB) for HTTP/HTTPS Layer 7 routing, Network Load Balancer (NLB) for Layer 4 ultra-low latency TCP/UDP, and the legacy Classic Load Balancer (CLB). Choosing the right one — and configuring it correctly — directly impacts your application's performance, availability, and cost.

1. ALB vs NLB vs CLB

FeatureALBNLBCLB
OSI Layer7 (HTTP/HTTPS)4 (TCP/UDP/TLS)4 and 7
Path routing
Host routing
Static IP❌ (use NLB→ALB)✅ per AZ
WebSocket
gRPC
Lambda targets
Latency~400ms overhead~100µs overheadMedium
StatusCurrentCurrentLegacy
Pro Tip: For new architectures, always choose ALB for HTTP/HTTPS workloads and NLB for everything else. Migrate CLBs immediately — CLB is not receiving new features.

2. Application Load Balancer (ALB)

Create an ALB with path-based routing via AWS CLI:

# Create ALB
aws elbv2 create-load-balancer \
  --name myapp-alb \
  --subnets subnet-public-1a subnet-public-1b \
  --security-groups sg-alb-external \
  --scheme internet-facing \
  --type application

# Create target groups
aws elbv2 create-target-group \
  --name myapp-api-tg \
  --protocol HTTP \
  --port 8080 \
  --vpc-id vpc-0abc1234 \
  --health-check-path /actuator/health \
  --health-check-interval-seconds 30 \
  --healthy-threshold-count 2 \
  --unhealthy-threshold-count 3

aws elbv2 create-target-group \
  --name myapp-frontend-tg \
  --protocol HTTP \
  --port 3000 \
  --vpc-id vpc-0abc1234 \
  --health-check-path /

# Create HTTPS listener with routing rules
LISTENER_ARN=$(aws elbv2 create-listener \
  --load-balancer-arn $ALB_ARN \
  --protocol HTTPS --port 443 \
  --certificates CertificateArn=arn:aws:acm:us-east-1:123456789:certificate/abc123 \
  --default-actions Type=forward,TargetGroupArn=$FRONTEND_TG_ARN \
  --query 'Listeners[0].ListenerArn' --output text)

# Add path-based rule for API
aws elbv2 create-rule \
  --listener-arn $LISTENER_ARN \
  --priority 10 \
  --conditions Field=path-pattern,Values='/api/*' \
  --actions Type=forward,TargetGroupArn=$API_TG_ARN

Weighted target groups for canary deployments — send 10% to v2:

aws elbv2 modify-rule \
  --rule-arn $RULE_ARN \
  --actions Type=forward,ForwardConfig='{
    "TargetGroups": [
      {"TargetGroupArn": "'$API_V1_TG_ARN'", "Weight": 90},
      {"TargetGroupArn": "'$API_V2_TG_ARN'", "Weight": 10}
    ],
    "StickinessDuration": 3600
  }'

3. Network Load Balancer (NLB)

# Create NLB with static Elastic IPs
aws elbv2 create-load-balancer \
  --name myapp-nlb \
  --type network \
  --scheme internet-facing \
  --subnet-mappings \
    SubnetId=subnet-1a,AllocationId=eipalloc-111 \
    SubnetId=subnet-1b,AllocationId=eipalloc-222

# TCP listener on port 443 (TLS passthrough to targets)
aws elbv2 create-listener \
  --load-balancer-arn $NLB_ARN \
  --protocol TCP --port 443 \
  --default-actions Type=forward,TargetGroupArn=$NLB_TG_ARN
Note: NLB preserves the client source IP by default. Update your Security Groups and application to allow traffic from client IP ranges — NLB doesn't have its own security group.

4. Target Groups and Health Checks

Well-tuned health checks prevent routing to unhealthy instances:

aws elbv2 modify-target-group \
  --target-group-arn $TG_ARN \
  --health-check-protocol HTTP \
  --health-check-path /actuator/health/liveness \
  --health-check-interval-seconds 15 \
  --health-check-timeout-seconds 5 \
  --healthy-threshold-count 2 \
  --unhealthy-threshold-count 2 \
  --matcher HttpCode=200

# Register targets (EC2 instances)
aws elbv2 register-targets \
  --target-group-arn $TG_ARN \
  --targets Id=i-instance1 Id=i-instance2

5. SSL/TLS Termination

Use ACM (AWS Certificate Manager) for free SSL certificates. Key settings:

  • Redirect HTTP → HTTPS: Add a port 80 listener with redirect action to port 443
  • Security policy: Use ELBSecurityPolicy-TLS13-1-2-2021-06 — requires TLS 1.2+, supports TLS 1.3
  • Multiple certificates: ALB supports SNI — attach multiple ACM certs for multiple domains
# HTTP → HTTPS redirect listener
aws elbv2 create-listener \
  --load-balancer-arn $ALB_ARN \
  --protocol HTTP --port 80 \
  --default-actions \
    Type=redirect,RedirectConfig='{Protocol=HTTPS,Port=443,StatusCode=HTTP_301}'

6. WAF Integration

# Associate WAF Web ACL with ALB
aws wafv2 associate-web-acl \
  --web-acl-arn arn:aws:wafv2:us-east-1:123456789:regional/webacl/MyWebACL/abc123 \
  --resource-arn $ALB_ARN

7. Access Logs

# Enable access logs to S3
aws elbv2 modify-load-balancer-attributes \
  --load-balancer-arn $ALB_ARN \
  --attributes \
    Key=access_logs.s3.enabled,Value=true \
    Key=access_logs.s3.bucket,Value=myapp-alb-logs \
    Key=access_logs.s3.prefix,Value=prod-alb \
    Key=idle_timeout.timeout_seconds,Value=60 \
    Key=routing.http2.enabled,Value=true

Frequently Asked Questions

When should I use NLB instead of ALB?

Use NLB when: you need a static IP address (for allowlisting by customers), you need ultra-low latency (gaming, financial trading), you're handling non-HTTP protocols (TCP, UDP), or you need to handle millions of requests per second. For standard web apps, ALB is almost always the right choice.

How do I get a static IP for my ALB?

ALBs don't support static IPs directly. The pattern is: put an NLB in front of the ALB. NLB gets static Elastic IPs, and you configure the NLB to forward to the ALB's DNS name. Alternatively, use Global Accelerator which provides static Anycast IPs backed by the ALB.

What is connection draining / deregistration delay?

When you deregister a target, the load balancer stops sending new requests but waits (default 300 seconds) for in-flight requests to complete before removing the target. Tune this to your request duration — for microservices with fast requests, 30–60 seconds is usually enough.

How do I troubleshoot 5xx errors from ALB?

502 = target returned invalid response or is unreachable. 503 = no healthy targets. 504 = target didn't respond within the idle timeout. Check: target health in the console, target security group allows ALB SG on the app port, application logs for errors, and CloudWatch access logs for detailed error info.