AWS ALB and ELB Load Balancing Setup
AWS provides managed load balancers without maintaining your own server. Application Load Balancer (ALB) works at HTTP/HTTPS level with routing by path and headers. Network Load Balancer (NLB) — L4 TCP/UDP with minimal latency. Classic ELB is deprecated.
Application Load Balancer
ALB is the standard choice for web apps. Routes by path, host, HTTP headers, method, query string. Integrates with ECS, EKS, Lambda, Auto Scaling Groups.
# Terraform: full ALB configuration
resource "aws_lb" "main" {
name = "myapp-alb"
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.alb.id]
subnets = aws_subnet.public[*].id
enable_deletion_protection = true
enable_cross_zone_load_balancing = true
drop_invalid_header_fields = true
access_logs {
bucket = aws_s3_bucket.alb_logs.bucket
enabled = true
}
tags = { Name = "myapp-alb" }
}
# HTTPS Listener
resource "aws_lb_listener" "https" {
load_balancer_arn = aws_lb.main.arn
port = 443
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-TLS13-1-2-2021-06"
certificate_arn = aws_acm_certificate.main.arn
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.web.arn
}
}
# HTTP → HTTPS redirect
resource "aws_lb_listener" "http" {
load_balancer_arn = aws_lb.main.arn
port = 80
protocol = "HTTP"
default_action {
type = "redirect"
redirect {
port = "443"
protocol = "HTTPS"
status_code = "HTTP_301"
}
}
}
# Target Group
resource "aws_lb_target_group" "web" {
name = "myapp-web-tg"
port = 8080
protocol = "HTTP"
vpc_id = aws_vpc.main.id
target_type = "ip"
health_check {
enabled = true
path = "/health"
healthy_threshold = 2
unhealthy_threshold = 3
timeout = 5
interval = 10
matcher = "200"
}
deregistration_delay = 30
stickiness {
type = "lb_cookie"
enabled = false
}
}
ALB Routing
# API on separate Target Group
resource "aws_lb_target_group" "api" {
name = "myapp-api-tg"
port = 3000
protocol = "HTTP"
vpc_id = aws_vpc.main.id
health_check {
path = "/api/health"
matcher = "200"
}
}
# Routing rules
resource "aws_lb_listener_rule" "api" {
listener_arn = aws_lb_listener.https.arn
priority = 10
action {
type = "forward"
target_group_arn = aws_lb_target_group.api.arn
}
condition {
path_pattern {
values = ["/api/*"]
}
}
}
# Weighted forwarding for Canary deployments
resource "aws_lb_listener_rule" "canary" {
listener_arn = aws_lb_listener.https.arn
priority = 20
action {
type = "forward"
forward {
target_group {
arn = aws_lb_target_group.web_stable.arn
weight = 95
}
target_group {
arn = aws_lb_target_group.web_canary.arn
weight = 5
}
stickiness {
enabled = true
duration = 3600
}
}
}
condition {
path_pattern { values = ["/*"] }
}
}
ALB + WAF
resource "aws_wafv2_web_acl" "main" {
name = "myapp-waf"
scope = "REGIONAL"
default_action { allow {} }
rule {
name = "AWSManagedRulesCommonRuleSet"
priority = 1
override_action { none {} }
statement {
managed_rule_group_statement {
name = "AWSManagedRulesCommonRuleSet"
vendor_name = "AWS"
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "CommonRuleSet"
sampled_requests_enabled = true
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "MyAppWAF"
sampled_requests_enabled = true
}
}
Timeline
| Configuration | Timeline |
|---|---|
| ALB + Target Group + HTTPS | 1–2 days |
| Routing by path/headers | +1 day |
| WAF + rate limiting | +1–2 days |
| Canary deployment via weighted forwarding | +1 day |
| Full Terraform with monitoring | 3–5 days |







