Home / AWS Cloud Architecture
AWS Networking & Compute Elasticity

AWS Load Balancers & Auto Scaling: ALB vs. NLB Enterprise Guide ⚖️

A production engineering breakdown of Elastic Load Balancing architectures. Master Layer-7 Application Load Balancers, ultra-low-latency Network Load Balancers, user-session affinity (Sticky Sessions), and dynamic Auto Scaling policies.

Published by AHP • cicdclouds.com

1. The Core Purpose of Elastic Load Balancing (ELB)

In modern cloud engineering, running monolithic application servers on single EC2 instances introduces fatal single points of failure (SPOF). When an instance crashes, undergoes kernel upgrades, or hits hardware resource starvation, users experience downtime.

AWS Elastic Load Balancing (ELB) distributes incoming application network traffic across multiple targets—such as EC2 instances, containers (ECS/EKS), and IP addresses—across multiple Availability Zones (AZs). This ensures automatic fault tolerance, seamless SSL/TLS termination, and zero-downtime rolling software deployments.

2. Architecture Selection: Application Load Balancer (ALB) vs. Network Load Balancer (NLB)

Selecting the right load balancer depends on protocol requirements, traffic patterns, and latency sensitivities:

Architecture Metric Application Load Balancer (ALB) Network Load Balancer (NLB)
OSI Network Layer Layer 7 (Application Layer) Layer 4 (Transport Layer)
Supported Protocols HTTP, HTTPS, gRPC, WebSockets TCP, UDP, TLS
Routing Capabilities Advanced content-based routing (Host header, URL Path, Query params) High-throughput IP/Port packet forwarding
Performance & Latency Single-digit millisecond latency Ultra-low microsecond latency; handles millions of requests/sec
Static IP Address ❌ No (Exposes dynamic DNS endpoint) ✅ Yes (Allocates 1 Elastic IP per Availability Zone)
Target Types Instance ID, Private IP, Lambda Function Instance ID, Private IP, Application Load Balancer
Typical Use Cases Microservices, Web Apps, Containerized APIs (EKS/ECS) Gaming servers, VoIP, Financial transactions, IoT streams

3. One-to-One User Behavior: Mastering Sticky Sessions (Session Affinity)

By default, an Application Load Balancer routes each incoming request independently to the target with the least active connections or via round-robin. However, legacy stateful applications often store user session data—such as login tokens or shopping cart states—in the local RAM of the specific backend EC2 instance.

To maintain a deterministic one-to-one user relationship, enable Sticky Sessions (Session Affinity). When enabled, the ALB assigns an HTTP cookie to the client browser, binding that specific user's requests to the exact same backend target instance for a defined duration.

Types of ALB Sticky Cookies:

  • Duration-Based Cookies (AWS Generated): The load balancer generates a signed cookie named AWSALB. You configure an expiration window (from 1 second to 7 days). If the target instance becomes unhealthy, the ALB automatically unbinds the session and routes the user to a healthy instance.
  • Application-Based Cookies: The backend application sets its own custom session cookie (e.g., JSESSIONID). The ALB generates a corresponding cookie (AWSALBAPP) that mirrors the application's session lifecycle.
# Enable Duration-Based Sticky Sessions on an ALB Target Group via AWS CLI
aws elbv2 modify-target-group-attributes \
  --target-group-arn "arn:aws:elasticloadbalancing:ap-south-1:123456789012:targetgroup/web-tg/abcdef123456" \
  --attributes \
    Key=stickiness.enabled,Value=true \
    Key=stickiness.type,Value=lb_cookie \
    Key=stickiness.lb_cookie.duration_seconds,Value=86400
Production Warning: While Sticky Sessions solve state locality, they create uneven traffic distribution (hot spotting) on backend servers. The modern cloud-native recommendation is to store session states in a distributed shared cache like Amazon ElastiCache (Redis), making your compute tier completely stateless.

4. Provisioning Elastic Compute: Launch Templates & Auto Scaling Groups

An Auto Scaling Group (ASG) monitors application workloads and automatically adjusts the number of running EC2 instances to maintain predictable performance at the lowest possible cost.

Step 1: Create a Version-Controlled Launch Template

Launch Templates supersede legacy Launch Configurations by supporting versioning, mixed Spot/On-Demand instance types, and automated T2/T3 unlimited credits:

# 1. Create Launch Template with bootstrap UserData script
aws ec2 create-launch-template \
  --launch-template-name enterprise-web-lt \
  --version-description "v1-nginx-production" \
  --launch-template-data '{
    "ImageId": "ami-0f5ee92e2d63afc18",
    "InstanceType": "t3.micro",
    "SecurityGroupIds": ["sg-0123456789abcdef0"],
    "UserData": "IyEvYmluL2Jhc2gKeXVtIHVwZGF0ZSAteQp5dW0gaW5zdGFsbCAteSBodHRwZApzeXN0ZW1jdGwgc3RhcnQgaHR0cGQKc3lzdGVtY3RsIGVuYWJsZSBodHRwZAplY2hvICI8aDE+SGVsbG8gZnJvbSBDSUNEQ2xvdWRzIEhvc3Q6ICQoaG9zdG5hbWUgLWYpPC9oMT4iID4gL3Zhci93d3cvaHRtbC9pbmRleC5odG1s",
    "TagSpecifications": [{
      "ResourceType": "instance",
      "Tags": [{"Key": "Environment", "Value": "Production"}]
    }]
  }'

Step 2: Deploy Multi-AZ Auto Scaling Group

Attach the ASG to the Application Load Balancer target group and distribute instances across at least two Availability Zones:

# 2. Provision Auto Scaling Group
aws autoscaling create-auto-scaling-group \
  --auto-scaling-group-name enterprise-web-asg \
  --launch-template LaunchTemplateName=enterprise-web-lt,Version='$Latest' \
  --min-size 2 \
  --max-size 10 \
  --desired-capacity 2 \
  --vpc-zone-identifier "subnet-0a1b2c3d4e5f6g7h8,subnet-0h7g6f5e4d3c2b1a0" \
  --target-group-arns "arn:aws:elasticloadbalancing:ap-south-1:123456789012:targetgroup/web-tg/abcdef123456" \
  --health-check-type ELB \
  --health-check-grace-period 300
Pro Tip: Always set --health-check-type ELB instead of the default EC2. The EC2 check only detects VM hardware degradation; the ELB health check verifies that your actual web server process (HTTP 200 on port 80/443) is alive and responding.

5. Intelligent CloudWatch Target Tracking Policies

Older scaling methods relied on simple CloudWatch alarms with manual step thresholds (e.g., "if CPU > 80%, add 2 instances"). Modern enterprise architectures implement Target Tracking Scaling Policies.

Like a household thermostat, you declare a desired metric target (e.g., maintain average CPU at 60%, or ALB Request Count per target at 1,000 requests/minute). CloudWatch continuously calculates the mathematical delta and scales instance counts proportionally up or down:

# 1. Attach CPU Target Tracking Policy
aws autoscaling put-scaling-policy \
  --auto-scaling-group-name enterprise-web-asg \
  --policy-name target-tracking-cpu-60 \
  --policy-type TargetTrackingScaling \
  --target-tracking-configuration '{
    "PredefinedMetricSpecification": {
      "PredefinedMetricType": "ASGAverageCPUUtilization"
    },
    "TargetValue": 60.0,
    "DisableScaleIn": false
  }'

# 2. Attach ALB Request Count per Target Policy
aws autoscaling put-scaling-policy \
  --auto-scaling-group-name enterprise-web-asg \
  --policy-name target-tracking-alb-requests \
  --policy-type TargetTrackingScaling \
  --target-tracking-configuration '{
    "PredefinedMetricSpecification": {
      "PredefinedMetricType": "ALBRequestCountPerTarget",
      "ResourceLabel": "app/enterprise-alb/1234567890abcdef/targetgroup/web-tg/abcdef123456"
    },
    "TargetValue": 1500.0
  }'

6. Production Troubleshooting & ELB Failure Patterns

When diagnosing traffic dropouts or scaling failures in production, look for these common error signatures:

1. HTTP 502 Bad Gateway

Root Cause: The Application Load Balancer successfully received the client's request, but the backend EC2 target closed the TCP connection prematurely or returned a malformed response header.

Remedy: Verify that the backend web server's Keep-Alive Timeout (e.g., Nginx keepalive_timeout or Apache KeepAliveTimeout) is configured to be higher than the ALB Idle Timeout (default is 60 seconds). If Nginx terminates the idle socket first, race conditions will trigger transient 502 errors.

2. HTTP 504 Gateway Timeout

Root Cause: The backend target accepted the TCP handshake but failed to respond within the load balancer's configured idle timeout period.

Remedy: Profile backend slow database queries or external API dependencies. If long-running batch requests are intentional, increase the ALB Idle Timeout attribute:

aws elbv2 modify-load-balancer-attributes \
  --load-balancer-arn "arn:aws:elasticloadbalancing:ap-south-1:123456789012:loadbalancer/app/enterprise-alb/1234567890abcdef" \
  --attributes Key=idle_timeout.timeout_seconds,Value=120

3. Targets Flapping in Health Checks (Instance Churn)

Root Cause: The health check threshold is too aggressive (e.g., 2 consecutive failures within 5 seconds), causing instances undergoing brief garbage collection or CPU spikes to be marked unhealthy and killed by the ASG.

Remedy: Set the health check grace period to at least 300 seconds to allow bootstrapping scripts to finish, and configure healthy/unhealthy thresholds to 3 consecutive probes with a 15-second interval.