AI Tools Compared

AI Tools for Automated Load Balancer Config 2026

Load balancer configuration involves trade-offs between performance, availability, and operational complexity. AI tools can generate correct configs quickly — but the details around health checks, timeouts, and TLS settings need to be explicitly specified.

HAProxy Configuration

Prompt to Claude:

Generate a production HAProxy config for a web application.
Backend: 3 app servers (app1:8080, app2:8080, app3:8080).
Requirements:
- HTTPS termination on port 443 (cert at /etc/ssl/myapp.pem)
- HTTP → HTTPS redirect on port 80
- Sticky sessions using a cookie
- Health checks every 5s, mark server down after 2 failures
- Connection limits: 200 max per backend server
- Enable compression for text/html, application/json
- Stats page at /haproxy-stats (password-protected)

Claude output:

global
    log /dev/log local0
    log /dev/log local1 notice
    maxconn 50000
    user haproxy
    group haproxy
    tune.ssl.default-dh-param 2048
    ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
    ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384

defaults
    log     global
    mode    http
    option  httplog
    option  dontlognull
    option  forwardfor
    option  http-server-close
    timeout connect 5s
    timeout client  30s
    timeout server  30s
    timeout http-request 10s
    timeout http-keep-alive 10s
    compression algo gzip
    compression type text/html application/json application/javascript text/css

frontend http_in
    bind *:80
    redirect scheme https code 301 if !{ ssl_fc }

frontend https_in
    bind *:443 ssl crt /etc/ssl/myapp.pem alpn h2,http/1.1
    default_backend app_servers

    # Security headers
    http-response set-header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
    http-response set-header X-Frame-Options SAMEORIGIN
    http-response set-header X-Content-Type-Options nosniff

backend app_servers
    balance roundrobin
    option httpchk GET /health HTTP/1.1\r\nHost:\ app.internal
    http-check expect status 200

    # Sticky sessions via cookie
    cookie SERVERID insert indirect nocache secure httponly

    # Connection limit per server
    default-server maxconn 200 inter 5s fall 2 rise 3 weight 100

    server app1 app1:8080 check cookie app1
    server app2 app2:8080 check cookie app2
    server app3 app3:8080 check cookie app3

listen stats
    bind *:8404
    stats enable
    stats uri /haproxy-stats
    stats realm "HAProxy Statistics"
    stats auth admin:${HAPROXY_STATS_PASSWORD}
    stats refresh 10s
    stats hide-version

Claude adds ALPN h2/http1.1 for HTTP/2 support, security headers on HTTPS responses, proper cookie flags (httponly secure), and nocache on the sticky cookie to prevent CDNs from caching the Set-Cookie header. It uses rise 3 (requires 3 successes to re-enable a server) alongside fall 2.

Nginx Upstream Configuration

Prompt:

Write Nginx upstream config for 4 backend servers with weighted routing:
server1 weight 3 (primary), server2 weight 3 (primary), server3 weight 1 (warm spare),
server4 weight 1 (warm spare). Passive health checks. Max 5 failed requests.
Keepalive pool of 64 connections. Include proxy timeouts.

Claude output:

upstream app_backend {
    least_conn;

    server app1.internal:8080 weight=3 max_fails=5 fail_timeout=30s;
    server app2.internal:8080 weight=3 max_fails=5 fail_timeout=30s;
    server app3.internal:8080 weight=1 max_fails=5 fail_timeout=30s;
    server app4.internal:8080 weight=1 max_fails=5 fail_timeout=30s;

    keepalive 64;
    keepalive_requests 1000;
    keepalive_timeout 60s;
}

server {
    listen 443 ssl http2;
    server_name app.example.com;

    ssl_certificate     /etc/nginx/ssl/app.crt;
    ssl_certificate_key /etc/nginx/ssl/app.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;

    location / {
        proxy_pass http://app_backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";  # Required for keepalive upstream

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_connect_timeout 5s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;

        proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
        proxy_next_upstream_tries 2;
        proxy_next_upstream_timeout 10s;
    }

    location /health {
        access_log off;
        return 200 "ok\n";
        add_header Content-Type text/plain;
    }
}

Claude correctly sets proxy_set_header Connection "" — required to enable HTTP/1.1 keepalive to the upstream (without it, Nginx sends Connection: close). It also includes proxy_next_upstream settings for automatic failover on 5xx responses.

AWS ALB with Terraform

Prompt:

Write Terraform for an AWS ALB with:
- Two target groups: blue (v1) and green (v2)
- Listener rule that sends 90% traffic to blue, 10% to green (weighted)
- Health checks on /health path, port 8080
- Access logs to S3 bucket
- Deletion protection enabled
resource "aws_lb" "app" {
  name               = "app-alb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.alb.id]
  subnets            = var.public_subnet_ids

  enable_deletion_protection = true

  access_logs {
    bucket  = aws_s3_bucket.alb_logs.id
    prefix  = "app-alb"
    enabled = true
  }
}

resource "aws_lb_target_group" "blue" {
  name        = "app-blue-v1"
  port        = 8080
  protocol    = "HTTP"
  vpc_id      = var.vpc_id
  target_type = "ip"

  health_check {
    path                = "/health"
    interval            = 30
    timeout             = 5
    healthy_threshold   = 2
    unhealthy_threshold = 3
    matcher             = "200"
  }
}

resource "aws_lb_target_group" "green" {
  name        = "app-green-v2"
  port        = 8080
  protocol    = "HTTP"
  vpc_id      = var.vpc_id
  target_type = "ip"

  health_check {
    path                = "/health"
    interval            = 30
    timeout             = 5
    healthy_threshold   = 2
    unhealthy_threshold = 3
    matcher             = "200"
  }
}

resource "aws_lb_listener" "https" {
  load_balancer_arn = aws_lb.app.arn
  port              = 443
  protocol          = "HTTPS"
  ssl_policy        = "ELBSecurityPolicy-TLS13-1-2-2021-06"
  certificate_arn   = var.acm_certificate_arn

  default_action {
    type = "forward"
    forward {
      target_group {
        arn    = aws_lb_target_group.blue.arn
        weight = 90
      }
      target_group {
        arn    = aws_lb_target_group.green.arn
        weight = 10
      }
    }
  }
}

Both Claude and ChatGPT produce correct ALB Terraform. Claude selects the TLS 1.3 security policy by default; ChatGPT often uses an older policy.

Rate Limiting and DDoS Protection

Load balancers are the first line of defense against traffic abuse. AI can generate the connection limiting and rate limiting configuration that’s often omitted from basic examples.

Prompt:

Add rate limiting to the Nginx config: max 20 requests/second per IP for the API,
max 100 connections per IP globally. Return 429 with Retry-After header when limited.
Also add bot protection that blocks known bad user agents.
# Rate limiting zones (defined in http {} block)
limit_req_zone $binary_remote_addr zone=api_rate:10m rate=20r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;

# Bot protection — map to a $bad_bot variable
map $http_user_agent $bad_bot {
    default         0;
    "~*scrapy"      1;
    "~*wget"        1;
    "~*python-requests" 1;
    "~*curl"        0;  # Allow curl for legitimate API testing
    ""              1;  # Block empty user agents
}

server {
    # ... ssl config omitted for brevity ...

    # Global connection limit
    limit_conn conn_limit 100;

    # Block bad bots
    if ($bad_bot = 1) {
        return 403 "Forbidden\n";
    }

    location /api/ {
        limit_req zone=api_rate burst=40 nodelay;
        limit_req_status 429;

        # Add Retry-After header when rate limited
        add_header Retry-After 1 always;

        proxy_pass http://app_backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

The burst=40 allows short spikes up to 40 requests before rate limiting kicks in — useful for legitimate clients that occasionally batch API calls. nodelay processes burst requests immediately rather than queueing them, which reduces latency for normal traffic. Claude explains this trade-off explicitly when you ask.

Cloudflare Workers for Edge Load Balancing

Modern traffic management extends beyond traditional load balancers. AI tools can generate Cloudflare Workers scripts for edge-level routing.

Prompt:

Write a Cloudflare Worker that implements canary routing:
- 5% of traffic goes to the canary origin (v2.api.example.com)
- 95% goes to the stable origin (api.example.com)
- Sticky canary assignment using a cookie (so the same user always hits canary)
- Log canary vs stable requests to a KV namespace
const CANARY_PERCENTAGE = 5;
const STABLE_ORIGIN = "https://api.example.com";
const CANARY_ORIGIN = "https://v2.api.example.com";
const COOKIE_NAME = "canary_group";

export default {
  async fetch(request, env) {
    const url = new URL(request.url);
    const cookies = parseCookies(request.headers.get("Cookie") || "");

    let isCanary;

    // Check existing sticky assignment
    if (cookies[COOKIE_NAME] === "1") {
      isCanary = true;
    } else if (cookies[COOKIE_NAME] === "0") {
      isCanary = false;
    } else {
      // New visitor — assign randomly
      isCanary = Math.random() * 100 < CANARY_PERCENTAGE;
    }

    const origin = isCanary ? CANARY_ORIGIN : STABLE_ORIGIN;
    const targetUrl = new URL(url.pathname + url.search, origin);

    const response = await fetch(targetUrl.toString(), {
      method: request.method,
      headers: request.headers,
      body: request.body,
    });

    // Log to KV
    await env.ROUTING_LOG.put(
      `${Date.now()}-${crypto.randomUUID()}`,
      JSON.stringify({
        path: url.pathname,
        canary: isCanary,
        status: response.status,
        timestamp: new Date().toISOString(),
      }),
      { expirationTtl: 86400 }
    );

    // Clone response and set sticky cookie
    const newResponse = new Response(response.body, response);
    newResponse.headers.append(
      "Set-Cookie",
      `${COOKIE_NAME}=${isCanary ? "1" : "0"}; Max-Age=86400; Path=/; SameSite=Lax; Secure`
    );
    return newResponse;
  },
};

function parseCookies(cookieHeader) {
  return Object.fromEntries(
    cookieHeader.split(";").map((c) => c.trim().split("=").map(decodeURIComponent))
  );
}

Claude correctly implements stickiness by checking the cookie before random assignment, which prevents users from flipping between groups on subsequent requests. The KV write uses expirationTtl to avoid unbounded log growth.

Comparing AI Tools for Load Balancer Config

For traditional load balancer configs (HAProxy, Nginx), Claude and GPT-4 both perform at a high level. The differences emerge in:

HAProxy: Claude consistently generates correct ACL syntax and uses the http-check directive for active health checks. GPT-4 occasionally uses deprecated option httpchk syntax without the http-check expect companion.

Nginx upstream: Both tools handle basic upstream config. Claude proactively adds proxy_next_upstream retry logic; GPT-4 often omits it unless explicitly requested.

Terraform (AWS ALB): Claude defaults to current TLS policies and includes enable_deletion_protection = true. GPT-4 leaves deletion protection unset (defaults to false), which is a production risk.

Edge routing (Cloudflare Workers, Lambda@Edge): Claude performs better on JavaScript-based edge routing — particularly around cookie parsing, response cloning, and handling streaming response bodies correctly.

For complex routing scenarios (weighted canary, A/B testing, geo-routing), provide explicit percentage values and specify the stickiness mechanism in your prompt. Both tools produce incorrect output when the routing logic is ambiguous.

Built by theluckystrike — More at zovo.one