Skip to content

ELB classic load balancers should have cross-zone load balancing enabled

Without cross-zone load balancing, a Classic ELB distributes traffic evenly across availability zones, not across instances. If one AZ has two instances and another has eight, the two instances in the smaller AZ each receive 25% of total traffic while the eight instances in the larger AZ each receive about 6%. This creates hotspots that degrade performance and increase the blast radius of an AZ failure.

Enabling cross-zone load balancing distributes requests evenly across all registered healthy instances regardless of AZ, which improves fault tolerance and reduces the operational burden of keeping instance counts perfectly balanced across zones.

Retrofit consideration

Enabling cross-zone load balancing on an existing Classic ELB changes traffic distribution immediately. Instances that previously received less traffic may see a sudden increase. Verify capacity and health check thresholds before applying.

Implementation

Choose the approach that matches how you manage Terraform.

Use the compliance.tf module to enforce this control by default. See get started with compliance.tf.

module "elb" {
  source  = "hipaa.compliance.tf/terraform-aws-modules/elb/aws"
  version = ">=4.0.0,<5.0.0"

  health_check = {
    healthy_threshold   = 2
    interval            = 30
    target              = "HTTP:80/"
    timeout             = 5
    unhealthy_threshold = 2
  }
  internal = true
  listener = [
    {
      instance_port     = 80
      instance_protocol = "HTTP"
      lb_port           = 80
      lb_protocol       = "HTTP"
    }
  ]
  name            = "abc123"
  security_groups = ["sg-abc12345"]
  subnets         = ["subnet-abc123", "subnet-def456"]
}

module "elb" {
  source  = "nist80053.compliance.tf/terraform-aws-modules/elb/aws"
  version = ">=4.0.0,<5.0.0"

  health_check = {
    healthy_threshold   = 2
    interval            = 30
    target              = "HTTP:80/"
    timeout             = 5
    unhealthy_threshold = 2
  }
  internal = true
  listener = [
    {
      instance_port     = 80
      instance_protocol = "HTTP"
      lb_port           = 80
      lb_protocol       = "HTTP"
    }
  ]
  name            = "abc123"
  security_groups = ["sg-abc12345"]
  subnets         = ["subnet-abc123", "subnet-def456"]
}

module "elb" {
  source  = "fedrampmoderate.compliance.tf/terraform-aws-modules/elb/aws"
  version = ">=4.0.0,<5.0.0"

  health_check = {
    healthy_threshold   = 2
    interval            = 30
    target              = "HTTP:80/"
    timeout             = 5
    unhealthy_threshold = 2
  }
  internal = true
  listener = [
    {
      instance_port     = 80
      instance_protocol = "HTTP"
      lb_port           = 80
      lb_protocol       = "HTTP"
    }
  ]
  name            = "abc123"
  security_groups = ["sg-abc12345"]
  subnets         = ["subnet-abc123", "subnet-def456"]
}

module "elb" {
  source  = "nist800171.compliance.tf/terraform-aws-modules/elb/aws"
  version = ">=4.0.0,<5.0.0"

  health_check = {
    healthy_threshold   = 2
    interval            = 30
    target              = "HTTP:80/"
    timeout             = 5
    unhealthy_threshold = 2
  }
  internal = true
  listener = [
    {
      instance_port     = 80
      instance_protocol = "HTTP"
      lb_port           = 80
      lb_protocol       = "HTTP"
    }
  ]
  name            = "abc123"
  security_groups = ["sg-abc12345"]
  subnets         = ["subnet-abc123", "subnet-def456"]
}

module "elb" {
  source  = "cisacyberessentials.compliance.tf/terraform-aws-modules/elb/aws"
  version = ">=4.0.0,<5.0.0"

  health_check = {
    healthy_threshold   = 2
    interval            = 30
    target              = "HTTP:80/"
    timeout             = 5
    unhealthy_threshold = 2
  }
  internal = true
  listener = [
    {
      instance_port     = 80
      instance_protocol = "HTTP"
      lb_port           = 80
      lb_protocol       = "HTTP"
    }
  ]
  name            = "abc123"
  security_groups = ["sg-abc12345"]
  subnets         = ["subnet-abc123", "subnet-def456"]
}

module "elb" {
  source  = "nydfs23.compliance.tf/terraform-aws-modules/elb/aws"
  version = ">=4.0.0,<5.0.0"

  health_check = {
    healthy_threshold   = 2
    interval            = 30
    target              = "HTTP:80/"
    timeout             = 5
    unhealthy_threshold = 2
  }
  internal = true
  listener = [
    {
      instance_port     = 80
      instance_protocol = "HTTP"
      lb_port           = 80
      lb_protocol       = "HTTP"
    }
  ]
  name            = "abc123"
  security_groups = ["sg-abc12345"]
  subnets         = ["subnet-abc123", "subnet-def456"]
}

module "elb" {
  source  = "ffiec.compliance.tf/terraform-aws-modules/elb/aws"
  version = ">=4.0.0,<5.0.0"

  health_check = {
    healthy_threshold   = 2
    interval            = 30
    target              = "HTTP:80/"
    timeout             = 5
    unhealthy_threshold = 2
  }
  internal = true
  listener = [
    {
      instance_port     = 80
      instance_protocol = "HTTP"
      lb_port           = 80
      lb_protocol       = "HTTP"
    }
  ]
  name            = "abc123"
  security_groups = ["sg-abc12345"]
  subnets         = ["subnet-abc123", "subnet-def456"]
}

module "elb" {
  source  = "eugmpannex11.compliance.tf/terraform-aws-modules/elb/aws"
  version = ">=4.0.0,<5.0.0"

  health_check = {
    healthy_threshold   = 2
    interval            = 30
    target              = "HTTP:80/"
    timeout             = 5
    unhealthy_threshold = 2
  }
  internal = true
  listener = [
    {
      instance_port     = 80
      instance_protocol = "HTTP"
      lb_port           = 80
      lb_protocol       = "HTTP"
    }
  ]
  name            = "abc123"
  security_groups = ["sg-abc12345"]
  subnets         = ["subnet-abc123", "subnet-def456"]
}

module "elb" {
  source  = "cfrpart11.compliance.tf/terraform-aws-modules/elb/aws"
  version = ">=4.0.0,<5.0.0"

  health_check = {
    healthy_threshold   = 2
    interval            = 30
    target              = "HTTP:80/"
    timeout             = 5
    unhealthy_threshold = 2
  }
  internal = true
  listener = [
    {
      instance_port     = 80
      instance_protocol = "HTTP"
      lb_port           = 80
      lb_protocol       = "HTTP"
    }
  ]
  name            = "abc123"
  security_groups = ["sg-abc12345"]
  subnets         = ["subnet-abc123", "subnet-def456"]
}

module "elb" {
  source  = "rbiitfnbfc.compliance.tf/terraform-aws-modules/elb/aws"
  version = ">=4.0.0,<5.0.0"

  health_check = {
    healthy_threshold   = 2
    interval            = 30
    target              = "HTTP:80/"
    timeout             = 5
    unhealthy_threshold = 2
  }
  internal = true
  listener = [
    {
      instance_port     = 80
      instance_protocol = "HTTP"
      lb_port           = 80
      lb_protocol       = "HTTP"
    }
  ]
  name            = "abc123"
  security_groups = ["sg-abc12345"]
  subnets         = ["subnet-abc123", "subnet-def456"]
}

module "elb" {
  source  = "fedramplow.compliance.tf/terraform-aws-modules/elb/aws"
  version = ">=4.0.0,<5.0.0"

  health_check = {
    healthy_threshold   = 2
    interval            = 30
    target              = "HTTP:80/"
    timeout             = 5
    unhealthy_threshold = 2
  }
  internal = true
  listener = [
    {
      instance_port     = 80
      instance_protocol = "HTTP"
      lb_port           = 80
      lb_protocol       = "HTTP"
    }
  ]
  name            = "abc123"
  security_groups = ["sg-abc12345"]
  subnets         = ["subnet-abc123", "subnet-def456"]
}

module "elb" {
  source  = "nistcsfv11.compliance.tf/terraform-aws-modules/elb/aws"
  version = ">=4.0.0,<5.0.0"

  health_check = {
    healthy_threshold   = 2
    interval            = 30
    target              = "HTTP:80/"
    timeout             = 5
    unhealthy_threshold = 2
  }
  internal = true
  listener = [
    {
      instance_port     = 80
      instance_protocol = "HTTP"
      lb_port           = 80
      lb_protocol       = "HTTP"
    }
  ]
  name            = "abc123"
  security_groups = ["sg-abc12345"]
  subnets         = ["subnet-abc123", "subnet-def456"]
}

module "elb" {
  source  = "nist80053rev4.compliance.tf/terraform-aws-modules/elb/aws"
  version = ">=4.0.0,<5.0.0"

  health_check = {
    healthy_threshold   = 2
    interval            = 30
    target              = "HTTP:80/"
    timeout             = 5
    unhealthy_threshold = 2
  }
  internal = true
  listener = [
    {
      instance_port     = 80
      instance_protocol = "HTTP"
      lb_port           = 80
      lb_protocol       = "HTTP"
    }
  ]
  name            = "abc123"
  security_groups = ["sg-abc12345"]
  subnets         = ["subnet-abc123", "subnet-def456"]
}

If you use terraform-aws-modules/elb/aws, set the right module inputs for this control. You can later migrate to the compliance.tf module with minimal changes because it is compatible by design.

module "elb" {
  source  = "terraform-aws-modules/elb/aws"
  version = ">=4.0.0,<5.0.0"

  health_check = {
    healthy_threshold   = 2
    interval            = 30
    target              = "HTTP:80/"
    timeout             = 5
    unhealthy_threshold = 2
  }
  internal = true
  listener = [
    {
      instance_port     = 80
      instance_protocol = "HTTP"
      lb_port           = 80
      lb_protocol       = "HTTP"
    }
  ]
  name            = "abc123"
  security_groups = ["sg-abc12345"]
  subnets         = ["subnet-abc123", "subnet-def456"]

  cross_zone_load_balancing = true
}

Use AWS provider resources directly. See docs for the resources involved: aws_elb.

resource "aws_elb" "this" {
  internal = true

  listener {
    instance_port     = 80
    instance_protocol = "http"
    lb_port           = 80
    lb_protocol       = "http"
  }

  subnets = ["subnet-abc123", "subnet-def456"]

  cross_zone_load_balancing = true
}

What this control checks

This control validates that the aws_elb resource has cross_zone_load_balancing set to true. Set it explicitly; omitting the argument leaves compliance dependent on Terraform's default. Setting cross_zone_load_balancing = false fails the control. The check applies only to Classic Load Balancers (aws_elb), not Application or Network Load Balancers (aws_lb), which handle cross-zone behavior differently.

Common pitfalls

  • Terraform default masks non-compliant imports

    Import a Classic ELB that was created with cross-zone disabled, and terraform plan may show no diff if the argument is omitted from your config. Always declare cross_zone_load_balancing = true explicitly so the next apply corrects the imported resource.

  • Control does not apply to ALBs or NLBs

    This control only evaluates aws_elb. ALBs have cross-zone load balancing permanently on at the load balancer level. NLBs are configured via aws_lb with enable_cross_zone_load_balancing, and that setting needs separate review since it's outside the scope of this check.

  • Uneven capacity after enabling

    Traffic distribution shifts immediately when cross-zone is enabled. If one AZ is running fewer or smaller instances, those instances can become overloaded within minutes. Check desired_capacity and instance types across AZs before flipping the setting.

Audit evidence

An auditor expects AWS Config rule evaluation results for elb-cross-zone-load-balancing-enabled showing all Classic ELBs as COMPLIANT. Supporting evidence includes CLI output from aws elb describe-load-balancer-attributes --load-balancer-name <name> with CrossZoneLoadBalancing.Enabled returning true for each load balancer. Screenshots from the EC2 console showing the "Cross-Zone Load Balancing" attribute as "Enabled" under a Classic ELB's description tab round out a complete evidence package.

For continuous compliance, Security Hub findings mapped to this control, or a third-party CSPM tool showing passing status over time, give auditors the historical record they need.

Framework-specific interpretation

HIPAA Omnibus Rule 2013: 45 CFR 164.308(a)(7) requires covered entities to protect the availability of ePHI systems, and an ELB with cross-zone disabled is one of the more direct ways that requirement can fail when AZ instance counts are uneven.

NIST SP 800-53 Rev 5: Even traffic distribution across AZs maps to CP-10 (System Recovery and Reconstitution) and SC-5 (Denial-of-Service Protection). Single-zone concentration is exactly the partial failure scenario both controls address.

FedRAMP Moderate Baseline Rev 4: CP-10 and SC-5 both apply here. Cross-zone distribution prevents the single-AZ traffic concentration that produces localized outages, which is the partial infrastructure failure scenario FedRAMP availability requirements are designed to address.

Tool mappings

Use these identifiers to cross-reference this control across tools, reports, and evidence.

  • Compliance.tf Control: elb_classic_lb_cross_zone_load_balancing_enabled

  • AWS Config Managed Rule: ELB_CROSS_ZONE_LOAD_BALANCING_ENABLED

  • Checkov Check: CKV_AWS_138

  • Powerpipe Control: aws_compliance.control.elb_classic_lb_cross_zone_load_balancing_enabled

  • Prowler Checks: elb_cross_zone_load_balancing_enabled, elbv2_cross_zone_load_balancing_enabled

  • AWS Security Hub Control: ELB.9

Last reviewed: 2026-03-09