Short version: An Application or Network Load Balancer costs ~$0.0225/hour, about $16/month, just to exist, plus capacity units. Classic Load Balancers run ~$18/month. Load balancers outlive the services behind them: the app gets torn down, the ALB keeps billing. Here's how to find load balancers with no real traffic or no healthy targets, and remove them safely.
Why idle load balancers linger
The hourly base charge is fixed - an ALB with zero requests bills the same ~$16/month as a busy one. Load balancers are usually created early (with an app or an IaC module) and deleted last, if ever. A handful of abandoned ALBs from old environments is real, recurring money.
Step 1 - List load balancers and their traffic
aws elbv2 describe-load-balancers \
--query 'LoadBalancers[].{Name:LoadBalancerName,Type:Type,ARN:LoadBalancerArn}' \
--output table
For an ALB, check request volume over the last 7 days (the metric dimension is the tail of the ARN, e.g. app/my-alb/50dc6c495c0c9188):
aws cloudwatch get-metric-statistics \
--namespace AWS/ApplicationELB \
--metric-name RequestCount \
--dimensions Name=LoadBalancer,Value=app/my-alb/50dc6c495c0c9188 \
--start-time "$(date -u -d '7 days ago' +%Y-%m-%dT%H:%M:%SZ)" \
--end-time "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
--period 86400 --statistics Sum \
--query 'Datapoints[].Sum'
Near-zero request counts over a week is a strong idle signal. (For NLBs, use the AWS/NetworkELB namespace and ActiveFlowCount.)
Step 2 - Check for empty or unhealthy target groups
A load balancer with no healthy targets is doing nothing useful:
for tg in $(aws elbv2 describe-target-groups \
--load-balancer-arn <lb-arn> \
--query 'TargetGroups[].TargetGroupArn' --output text); do
echo "== $tg =="
aws elbv2 describe-target-health --target-group-arn "$tg" \
--query 'TargetHealthDescriptions[].TargetHealth.State' --output text
done
Empty output (no targets) or all unhealthy alongside near-zero requests is a confident "delete me."
Step 3 - Delete safely
aws elbv2 delete-load-balancer --load-balancer-arn <lb-arn>
Caveat: a load balancer with no requests isn't always dead - it might be a disaster-recovery endpoint, a rarely-hit admin panel, or the target of a DNS record something depends on. Before deleting, check Route 53 (and any external DNS) for records pointing at the load balancer's DNS name, and confirm nothing references it:
aws elbv2 describe-load-balancers --load-balancer-arn <lb-arn> \
--query 'LoadBalancers[].DNSName' --output text
Then grep your DNS zones for that name. No references + no traffic + no healthy targets = safe to remove.
Doing it across every account, automatically
Pulling CloudWatch for every load balancer by hand doesn't scale. It's one of the checks in a read-only CLI I built, Cloud Cost Analyzer - its idle-load-balancer rule flags load balancers serving fewer than 100 requests/day over a 7-day window, alongside 89 other AWS cost rules:
curl -sSL https://releases.dragonfractal.com/install.sh | sh
cca scan --provider aws
It runs in your environment with read-only access, so your AWS credentials never leave it. Free tier if you want to try it on one account, and dashboards if you want to review or share reports.
Originally published on the Dragon Fractal Cloud Cost Analyzer blog.
Top comments (0)