Skip to content
All writing Part 12 of 12 · Remote-Controlling Chrome in Containers
Engineering · 4 min read

noKeepAlive: Fresh TCP for Scaling Pods

Go's default HTTP client reuses TCP connections, bypassing DNS. With KEDA scale-down, reused connections point to dead pods. One setting fixes it.

The Problem

Go’s default HTTP client reuses TCP connections. That saves time when the server stays put. Chrome pods are not a fixed server. KEDA scales them up and down. A reused connection can point to a pod that no longer exists.

Default client (keep-alive ON): Req 1 → TCP to 10.0.1.5 → works → keeps pipe open KEDA scales down → 10.0.1.5 is GONE Req 2 → reuses old pipe → BROKEN (skips DNS, sends to dead pod) BROKEN noKeepAliveClient (keep-alive OFF): Req 1 → TCP to 10.0.1.5 → works → closes pipe KEDA scales down → 10.0.1.5 is gone Req 2 → DNS lookup → new pod IPs → works (fresh lookup every time) OK

Why Keep-Alive Bypasses DNS

A keep-alive connection is a direct TCP pipe to one pod IP. The client holds the pipe open. On the next request, the client sends data through the same pipe. It never asks DNS again.

keep-alive ON: DNS → pod IP → TCP open ────► reuse ────► reuse (no DNS, no DNS) keep-alive OFF: DNS → pod IP → TCP open → close → DNS → pod IP → TCP open → close

The Fix

One setting. Every request opens a new TCP connection and closes it when done. The 5-second timeout prevents hanging on an unreachable pod.

var noKeepAliveClient = &http.Client{
    Transport: &http.Transport{DisableKeepAlives: true},
    Timeout:   5 * time.Second,
}

Three Defenses That Work Together

Remove any one and the system breaks in a different way.

Defense Without it Headless Service DNS returns pod IPs Proxy routes randomly → GUID race Atomic round-robin Distributes across pods All goroutines pick same pod → uneven load DisableKeepAlives Fresh TCP per request Stale TCP to dead pods → failures after scale-down

Do not add a connection pool. A pool holds open connections to pod IPs that KEDA can remove at any time. Chrome pod HTTP calls must stay poolless.


References:

Related: see the headless Service that provides the pod IPs, or go back to the series overview.

Tags #kubernetes #chrome-devtools #containers
// connect

Be brave | Be wise | Be grateful

21 BreakinCode

// elsewhere
LinkedInMedium (lang: en)Life RecordYoutube
wh:~$William Hung· © 2026 Taipei · GMT+8 · Available for collaboration