## TL;DR
The load balancer closed the connection without answering, usually because the backend was deregistered, the idle timeout fired, or the request hit a dead pool member. Check LB target health first, then align keep-alive and idle timeouts between Playwright and the LB. If the origin is healthy and the LB still empties responses, the LB config is the bug.

```text
playwright request failed net::ERR_EMPTY_RESPONSE behind load balancer
```

## Use this when
- The error appears only through the load balancer, never direct to origin.
- Failures cluster after idle periods or during deploys.
- The LB is AWS ALB/NLB, GCP, Cloudflare, or nginx/haproxy.

## Not for this skill when
- Direct-to-origin requests also fail. That is the backend, not the balancer.
- The error is ERR_CONNECTION_RESET. That is a reset, a different failure.

## Steps
1. Check the LB target health: every backend should be healthy at the moment of failure. Verify: no targets flapping or draining during the failure window.
2. Compare idle timeouts: the LB's idle timeout must exceed the longest gap between requests on a reused connection. Verify: raising the LB idle timeout (e.g. ALB 60s default) stops the failures.
3. Disable connection reuse for the test: new Playwright context per batch. Verify: failures disappear, confirming stale pooled connections through the LB.
4. Check sticky sessions: if the app needs stickiness and the LB routes to a dead member, the response empties. Verify: stickiness settings match what the app expects.
5. During deploys, confirm connection draining is enabled with a drain timeout longer than in-flight requests. Verify: deploys stop producing empty responses.

## Variant phrasings
### ERR_EMPTY_RESPONSE load balancer
The short search, same LB-first diagnosis.
### playwright empty response alb
Vendor phrasing, points at the idle-timeout check.
### load balancer closes connection no response
Symptom phrasing, lands on step 1.

Compatibility: Playwright 1.x, any LB. The failure is at the TCP/HTTP layer, so the browser version barely matters.

## Why it happens
An empty response means someone closed the TCP connection without writing an HTTP response. Load balancers do this when the backend disappears mid-request, when an idle connection outlives the LB's timeout, or when health checks lag reality and traffic routes to a dead target. The browser cannot distinguish these; only the LB's logs can.

## Edge cases / pitfalls
- Playwright's connection pooling keeps sockets open longer than curl's one-shot requests, so the bug shows in Playwright first. That does not make it a Playwright bug.
- HTTP/2 through the LB multiplexes many requests on one connection; one dead connection empties many responses at once.
- Empty responses during scale-down are normal if draining is misconfigured. Fix the drain, not the client.
- Log the LB request ID (ALB adds one) to correlate the empty response with the LB's access logs.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_HUDXJaSSFRGeEbVm1qnVXg
