Load balancers are the front door of almost every highly available service on AWS.
Elastic Load Balancing offers three types:
- Application Load Balancer (ALB): layer 7. Routes HTTP and HTTPS by host, path, header or query string; supports WebSockets, gRPC, redirects, fixed responses, OIDC authentication and AWS WAF. Targets can be instances, IP addresses (containers) or Lambda functions.
- Network Load Balancer (NLB): layer 4. TCP, UDP and TLS with very high throughput and low latency, one static IP per AZ (or your Elastic IPs), and client source IPs preserved. Use it for non-HTTP protocols, static IP needs, and PrivateLink services.
- Gateway Load Balancer: for inserting third-party firewalls and appliances.
The pieces: a load balancer in subnets of at least two AZs (public for internet-facing, private for internal), listeners (protocol and port, with rules), and target groups that hold targets and define health checks. Unhealthy targets stop receiving traffic. When a target is removed, the deregistration delay (300 s by default) lets in-flight requests finish.
Terminate TLS on the load balancer with a free certificate from ACM, and redirect HTTP to HTTPS. Put a security group on the ALB and let targets accept traffic only from that SG.
Cross-zone load balancing spreads requests evenly across all targets in all AZs; it is always on for ALBs and off by default for NLBs, where enabling it adds inter-AZ data charges.
Make health-check endpoints cheap and honest: they should fail when the instance truly can't serve, but not when a shared dependency is down, or every target fails at once.
Example
TG=$(aws elbv2 create-target-group --name web-tg --protocol HTTP --port 8080 \
--vpc-id vpc-0a1b2c3d --target-type ip --health-check-path /healthz \
--query 'TargetGroups[0].TargetGroupArn' --output text)
LB=$(aws elbv2 create-load-balancer --name web-alb --type application \
--subnets subnet-pub-a subnet-pub-b --security-groups sg-0web \
--query 'LoadBalancers[0].LoadBalancerArn' --output text)
aws elbv2 create-listener --load-balancer-arn "$LB" --protocol HTTPS --port 443 \
--certificates CertificateArn=arn:aws:acm:eu-west-1:111122223333:certificate/abcd-1234 \
--default-actions Type=forward,TargetGroupArn="$TG"
aws elbv2 create-listener --load-balancer-arn "$LB" --protocol HTTP --port 80 \
--default-actions 'Type=redirect,RedirectConfig={Protocol=HTTPS,Port=443,StatusCode=HTTP_301}'
aws elbv2 register-targets --target-group-arn "$TG" --targets Id=10.20.10.15 Id=10.20.11.22
aws elbv2 describe-target-health --target-group-arn "$TG" \
--query 'TargetHealthDescriptions[].[Target.Id,TargetHealth.State]' --output text
# 10.20.10.15 healthy
# 10.20.11.22 initialRemember
- ALB for HTTP routing, NLB for TCP/UDP, static IPs and PrivateLink
- Listener -> rules -> target group -> health-checked targets
- Terminate TLS on the LB with ACM; targets accept traffic only from the LB's SG
- Health checks should reflect the target, not shared dependencies
Watch out for
- A health check that queries the database, so a DB blip marks every target unhealthy at once.