Application Load Balancer Traffic

Learn to balance traffic with an Application Load Balancer in this AWS Tutorial. Step 24 covers core concepts, hands-on setup, and troubleshooting.

Focus: balance traffic with an application load balancer

Sponsored

Your API is growing. More users, more requests, more instances. Soon you’ll find one server drowning while another idles — a classic sign of unbalanced traffic. Without a load balancer, you’re either over-provisioning (wasting money) or under-provisioning (losing users). This lesson shows you how to balance traffic with an Application Load Balancer (ALB) — the AWS service that intelligently distributes requests across your EC2 instances, containers, or Lambda functions, keeping your application fast and resilient.

The problem this lesson solves

Imagine you launch a small web app on a single EC2 instance. It works fine — until a viral post hits. Suddenly, thousands of requests flood in, your CPU spikes, and users see timeouts. The classic fix is to add more instances, but then you hit a new problem: which instance handles which request? If you hardcode the IP of one instance, the others sit idle. If you round-robin manually, you’re stuck updating DNS records every time you scale.

Without a load balancer, you face:

  • Single point of failure — one instance goes down, your app is down.
  • Uneven resource usage — some instances are maxed out, others idle.
  • Manual scaling — you can’t easily add or remove instances without changing DNS.
  • Poor user experience — slow responses, connection resets, downtime.

The Application Load Balancer solves all of this by sitting in front of your instances and routing each request to the healthiest, most available target. It’s the backbone of any resilient, scalable AWS architecture.

Core concept / mental model

Think of the ALB as a smart receptionist at a busy office. A client walks in (sends an HTTP request) — the receptionist (ALB) checks which employee (EC2 instance) is free and capable (healthy) and directs the client to them. The client doesn’t know or care which employee they get; they just get served quickly.

More formally, an ALB is a Layer 7 (HTTP/HTTPS) load balancer. It examines the request’s content — path, headers, query parameters — and uses rules to route traffic to different target groups. Each target group contains one or more instances (or Lambda functions) that the ALB monitors via health checks. If an instance fails a health check, the ALB stops sending traffic to it and reroutes to healthy ones.

Key pieces of the model:

  • Listener — the entry point. It listens on a port (usually 80 or 443) and defines the protocol.
  • Rules — logic that says “if path is /api, go to target group A; if path is /static, go to target group B.”
  • Target group — a logical group of instances. You define health checks and traffic distribution at this level.
  • Health checks — periodic requests (e.g., GET /health) that verify an instance is alive and ready.

The ALB is elastic — it scales automatically as traffic changes, and it integrates with auto scaling groups to add/remove instances based on demand.

How it works step by step

  1. Create your instances — Launch two or more EC2 instances running your web app. They should be identical (same AMI, user data) so any instance can serve any request.
  2. Create a target group — In the EC2 console, create a target group with a name, protocol (HTTP), port (80), and VPC. Set health check path (e.g., /health). Register both instances as targets.
  3. Create the ALB — Go to Load Balancers -> Create Load Balancer -> Application Load Balancer. Choose the scheme (internet-facing for public traffic), listeners (HTTP:80, or HTTPS:443 if you have a certificate), and the same VPC and subnets.
  4. Attach the target group — In the ALB’s listener, add a default action that forwards to your target group.
  5. Test — Get the ALB’s DNS name from the console, open it in a browser. Refresh multiple times: you should see responses from different instances (if your app displays instance ID).
  6. Clean up — Delete the ALB, target group, and instances to avoid charges.

The ALB automatically polls health checks. If an instance fails, it’s deregisted and traffic goes only to healthy ones. This is the safety net that keeps your app alive during failures.

Hands-on walkthrough

Let’s put it into practice. For this exercise, we’ll create two simple HTTP servers on EC2 instances and balance traffic between them.

Step 1: Launch two EC2 instances

Use the AWS CLI (or console). We’ll need a security group that allows HTTP on port 80 from anywhere (for the ALB to reach instances) and SSH from your IP.

# Create security group
alb_sg_id=$(aws ec2 create-security-group --group-name alb-example-sg --description "ALB example SG" --vpc-id <your-vpc-id> --query 'GroupId' --output text)

# Allow HTTP from anywhere (ALB will send traffic on port 80)
aws ec2 authorize-security-group-ingress --group-id $alb_sg_id --protocol tcp --port 80 --cidr 0.0.0.0/0
aws ec2 authorize-security-group-ingress --group-id $alb_sg_id --protocol tcp --port 22 --cidr <your-ip>/32

# Launch two instances with a simple user data script
aws ec2 run-instances --image-id ami-0c55b159cbfafe1f0 --instance-type t2.micro \
  --subnet-id <subnet-a> --security-group-ids $alb_sg_id \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=web1}]' \
  --user-data '
    #!/bin/bash
    yum update -y
    yum install -y httpd
    systemctl start httpd
    systemctl enable httpd
    echo "$(hostname -f) - Instance 1" > /var/www/html/index.html
    echo "OK" > /var/www/html/health
  '

# Repeat for instance 2 with different subnet and tag

Note: Use a real AMI ID for your region. The above is placeholders. Also, use different subnets (across AZs) for high availability.

Step 2: Create a target group

# Create target group
tg_arn=$(aws elbv2 create-target-group --name web-tg --protocol HTTP --port 80 \
  --vpc-id <your-vpc-id> --health-check-path /health --query 'TargetGroups[0].TargetGroupArn' --output text)

# Register instances (replace with instance IDs)
aws elbv2 register-targets --target-group-arn $tg_arn --targets Id=i-0abc123 Id=i-0def456

Step 3: Create the ALB and attach the target group

# Create ALB
lb_arn=$(aws elbv2 create-load-balancer --name my-alb --subnets subnet-a subnet-b \
  --scheme internet-facing --security-groups $alb_sg_id \
  --query 'LoadBalancers[0].LoadBalancerArn' --output text)

# Create a listener on port 80
tg_default_arn=$tg_arn
listener_arn=$(aws elbv2 create-listener --load-balancer-arn $lb_arn \
  --protocol HTTP --port 80 \
  --default-actions Type=forward,TargetGroupArn=$tg_default_arn \
  --query 'Listeners[0].ListenerArn' --output text)

# Get DNS name
alb_dns=$(aws elbv2 describe-load-balancers --load-balancer-arns $lb_arn --query 'LoadBalancers[0].DNSName' --output text)
echo "ALB DNS: $alb_dns"

Step 4: Test the balance

# Send multiple requests and see which instance responds
for i in {1..10}; do
  curl -s $alb_dns
  echo ""
done

Expected output (if instances are in order): a mix of "Instance 1" and "Instance 2" responses, demonstrating that traffic is distributed.

Also verify health checks:

# Check target health
aws elbv2 describe-target-health --target-group-arn $tg_arn

You should see healthy for both targets.

Step 5: Test failure handling

Stop one instance (or terminate it). Then run the curl loop again — the ALB should automatically route all traffic to the remaining instance. This is the core resilience feature.

Compare options / when to choose what

ALB isn’t the only AWS load balancer. Here’s when to choose what:

Load Balancer Layer Best for Use case example
Application Load Balancer Layer 7 (HTTP/HTTPS) Microservices, HTTP routing, path/host-based rules REST APIs, web apps with separate API and frontend
Network Load Balancer Layer 4 (TCP/UDP) Extreme performance, static IPs, low latency Game servers, TCP-based protocols, real-time apps
Classic Load Balancer Layer 4/7 Legacy setups, simple apps Older architectures with simple needs

ALB vs NLB — ALB is more feature-rich for HTTP: path-based routing, host-based routing, websocket support, and integration with AWS WAF. NLB handles millions of requests per second and preserves source IPs, but lacks HTTP-aware routing.

ALB vs Route53 — Route53 does DNS-level load balancing (round-robin, failover) but doesn’t inspect HTTP. ALB is needed for fine-grained traffic management.

For most web applications, the ALB is the right choice. It’s the default recommendation for new applications on EC2 or ECS.

Troubleshooting & edge cases

  • Health check failing — Your instances aren’t responding to GET /health with 200. Check that the web server is running, the health file is in the right path, and the security group allows inbound HTTP from the ALB’s security group (or from anywhere). Use curl http://<instance-ip>/health on each instance manually.

  • ALB returns 503 — This means no healthy targets. Verify target health with describe-target-health. If targets are unhealthy, debug the health check path and instance reachability.

  • DNS is not resolving — Wait a few minutes after creating the ALB; DNS propagation takes time. Use the exact DNS name from the console (or .elb.amazonaws.com), not an IP, because ALBs don’t have static IPs.

  • Intermittent 504 from the ALB — Your instance is too slow to respond within the idle timeout (default 60 seconds). Increase the timeout, or optimize your app.

  • Traffic not balanced evenly — The default algorithm is round-robin for ALB, but instances may have different weights. Check your target groups — you can assign weights. Also, if one instance is slower, ALB may send fewer requests to it.

  • Sticky sessions needed? — If your app stores state on the instance, enable sticky sessions in the target group rules to bind a session to a specific instance. But for stateless apps, avoid it for better load distribution.

What you learned & what's next

You now understand why you need an ALB, how it works at a high level, and you’ve created one with hands-on steps. You can:

  • Explain the ALB’s role in a scalable architecture.
  • Create a target group, register instances, and set up health checks.
  • Create an ALB with a listener and forward traffic.
  • Test traffic distribution and failure handling.
  • Choose between ALB, NLB, and Classic LB for different use cases.

Next in the track, you’ll learn about Auto Scaling — a natural companion to load balancing. Auto scaling automatically adjusts the number of instances based on demand, making your ALB’s job even more efficient.

Review your ALB setup, and make sure to clean up resources to avoid costs. Then move on to the next lesson!

Practice recap

In this short exercise, you'll solidify your understanding of ALB health checks. Launch two EC2 instances with your web app, set up the ALB and target group using the steps above, then deliberately stop one instance. Run a loop of curl requests and observe how the ALB immediately routes all traffic to the remaining healthy instance. This hands-on verifies the resilience ALB provides and prepares you for the next lesson on Auto Scaling.

Common mistakes

  • Forgetting to open port 80 to the ALB's security group in the instance security group, leading to all targets unhealthy.
  • Setting the health check path to something that doesn't return 200 (e.g., a missing file), causing the ALB to drop traffic to healthy instances.
  • Not placing instances across multiple Availability Zones, defeating the purpose of load balancing and high availability.
  • Misunderstanding the ALB's DNS name — ALBs don't have static IPs, so using an IP will fail after changes.

Variations

  1. Use a Network Load Balancer (NLB) for ultra-low latency, static IPs, or TCP/UDP traffic where HTTP awareness is unnecessary.
  2. Use sticky sessions (session affinity) on the ALB to bind a user to the same instance when your app requires session state.
  3. Integrate the ALB with AWS WAF to filter malicious traffic before it reaches your instances.

Real-world use cases

  • Distributing HTTP traffic for a multi-tier web app across EC2 instances in different AZs to ensure high availability.
  • Routing API requests to separate backend services using path-based rules (/api vs /admin) on a single ALB.
  • Load balancing traffic for containerized apps on ECS, where the ALB dynamically targets tasks across a cluster.

Key takeaways

  • An ALB routes HTTP/HTTPS traffic at Layer 7 to healthy targets based on rules and health checks.
  • Target groups define the instances (or Lambda) that receive traffic and their health check configuration.
  • Health checks are critical — they keep traffic off failing instances and maintain availability.
  • Place instances across multiple Availability Zones for true high availability.
  • ALB DNS name is the endpoint; it changes over time, so use that name instead of IP addresses.
  • ALB is ideal for most web applications, but NLB exists for TCP/UDP and extreme performance.

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.