Skip to content

Classic Load Balancers should have connection draining enabled

When an instance is removed from a Classic Load Balancer without connection draining, active TCP connections are immediately severed. Users experience dropped requests, failed uploads, or broken transactions mid-stream. This causes visible errors during deployments, Auto Scaling scale-in events, and health check failures.

Enabling connection draining gives existing connections a configurable timeout (up to 3600 seconds, default 300) to finish naturally. The cost is zero. The risk of leaving it off is user-facing errors every time your fleet changes.

Implementation

Choose the approach that matches how you manage Terraform.

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"]

  connection_draining = 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"]

  connection_draining = true
}

What this control checks

The aws_elb resource must have connection_draining = true. connection_draining_timeout is optional; it accepts an integer in seconds (default 300, max 3600) and controls how long the load balancer waits for existing connections to finish. A configuration passes when connection_draining = true. It fails when connection_draining is omitted (it defaults to false) or explicitly set to false.

Common pitfalls

  • Default is false

    Omitting connection_draining on aws_elb defaults it to false, so teams copying minimal examples or auto-generating resources will fail this control silently.

  • Timeout too short for long-lived connections

    Setting connection_draining_timeout to a very low value (e.g., 5 seconds) technically passes this control but may still drop long-running requests like file uploads or streaming HTTP responses. Choose a timeout that matches your application's longest expected request duration.

  • Classic LBs created outside Terraform

    CLBs provisioned via the AWS Console, CloudFormation, or SDK calls may not have connection draining enabled. Importing them with terraform import aws_elb does not automatically fix the setting; you must explicitly add connection_draining = true to the resource configuration.

Audit evidence

Config rule evaluation results showing all CLBs as compliant are the primary evidence. Prowler or Steampipe reports covering the same check work equally well. In the console, EC2 > Load Balancers > [Classic LB] > Description tab should display "Connection Draining: Enabled" with the configured timeout. For CLI verification, run aws elb describe-load-balancer-attributes --load-balancer-name <name> and confirm ConnectionDraining.Enabled is true for each CLB in scope.

Tool mappings

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

  • Compliance.tf Control: ec2_classic_lb_connection_draining_enabled

  • Powerpipe Control: aws_compliance.control.ec2_classic_lb_connection_draining_enabled

  • Prowler Check: elb_connection_draining_enabled

  • AWS Security Hub Control: ELB.7

Last reviewed: 2026-03-09