Proxy Idle Timeout and Keep-Alive Test: Prevent Stale Connection Failures

Sunlit ceramic Internet network with copper routes passing through connection-lifecycle checkpoints

A proxy request can succeed, sit idle, and fail on the next reuse even though the client still believes the socket is available. The origin, proxy gateway, load balancer, firewall, NAT device or client pool may each apply a different idle lifetime. If the application discovers that mismatch only when real work arrives, users see resets, empty responses, latency spikes or unnecessary retries.

This guide builds an authorized, repeatable test for the safe reuse window. It treats HTTP persistence, TCP keepalive probes, proxy-session lifetime and application timeouts as separate controls.

Name every timeout before tuning

Create an inventory instead of using one vague “proxy timeout” field:

  • proxy connection establishment timeout;
  • destination connection and TLS handshake timeout;
  • response-header timeout;
  • response-body inactivity timeout;
  • client pool idle timeout;
  • gateway or intermediary idle timeout;
  • TCP keepalive probe start, interval and count;
  • HTTP/2 or HTTP/3 session and stream limits;
  • residential sticky-session lifetime;
  • total request deadline and retry budget.

These timers answer different questions. A sticky-session lifetime describes exit selection, not necessarily the lifetime of one TCP connection. TCP keepalive can detect a dead peer, but it does not guarantee that an HTTP connection remains reusable or that an upstream mapping still exists.

Use deterministic fixtures

Test only endpoints you own or are explicitly authorized to exercise. Prepare:

  1. a small response with a known digest;
  2. a larger response that exposes mid-body interruption;
  3. an endpoint that reports a sanitized connection identifier;
  4. an endpoint that can delay headers or body chunks in a controlled test environment;
  5. a clean close and an abrupt close fixture;
  6. HTTP/1.1 and HTTP/2 paths where both matter.

Keep the request method, headers, proxy credentials, market, address family and client build fixed. Do not use a changing public page as the only proof of reuse.

Capture evidence at three layers

For each attempt, record a sanitized row such as:

trial_id
proxy_route_alias
session_alias
protocol
address_family
requested_market
observed_market
connection_id
idle_gap_ms
socket_age_ms
reused_connection
status_code
response_digest
failure_phase
error_class
attempt_count
time_to_useful_result_ms

Add client pool counters, operating-system socket state and proxy-provider telemetry when available. Never log proxy passwords, tokens, cookies, raw customer data or unrestricted payloads.

Find the practical reuse boundary

Run a controlled idle-gap ladder. Establish a connection, complete a validated request, wait, then send the same request through the same pool:

0 s -> 1 s -> 5 s -> 15 s -> 30 s -> 60 s -> 120 s -> 300 s

Repeat each gap enough times to expose intermittent closure. Once failures begin, narrow the boundary with additional gaps. Randomize the order across routes so a temporary origin issue does not affect only the longest waits.

Count a reuse as successful only when the response completes, its digest and semantic assertions pass, and the observed market and session behavior remain correct. A new connection that silently replaces a stale one is a successful request but not a successful reuse; record it separately.

Compare direct and proxy paths

Use a direct control where policy permits, then repeat through each required route:

  • authenticated HTTP or HTTPS proxy;
  • SOCKS5 with the intended DNS mode;
  • rotating residential route;
  • sticky residential session;
  • static or dedicated exit;
  • required IPv4 and IPv6 paths;
  • Global, North America, Europe and APAC markets in scope.

If the direct path and proxy path fail at the same idle gap, inspect the origin, client or shared network first. If only the proxy path fails, isolate gateway, tunnel, NAT and route-specific policy. Do not assume every reset came from the provider.

Distinguish four outcomes

Classify the first request after the gap:

  1. Safe reuse: the original connection carries a complete valid response.
  2. Clean retirement: the pool detects closure and opens a new connection before sending application bytes.
  3. Transparent recovery: stale reuse fails, but one safe bounded retry establishes a new connection and returns a valid result.
  4. User-visible failure: the request is lost, corrupted, duplicated or delayed beyond the service objective.

Clean retirement is usually preferable to discovering a stale socket during work. Transparent recovery is acceptable only when the operation is safe to retry and its extra latency and cost fit the budget.

Test half-open and race conditions

Idle failures often occur near a boundary, not at an exact second. In a controlled environment, test:

  • proxy closes first while the client pool still marks the socket idle;
  • origin closes its side of a tunnel;
  • network state disappears without an orderly close;
  • a request begins as an idle-reaper runs;
  • several workers select the same aging connection;
  • cancellation and shutdown occur during reuse;
  • HTTP/2 GOAWAY or stream reset arrives near a new request.

Verify that one connection failure does not replay unsafe operations, leak listeners, affect unrelated multiplexed streams or trigger a retry storm.

Set the client retirement margin

Choose a client pool idle limit shorter than the lowest reliable intermediary boundary, with a margin for scheduling jitter, network delay and configuration drift. Do not copy the median observed cutoff. Use a conservative percentile across route classes and markets.

If different routes have materially different boundaries, maintain route-specific pools or use the safest shared limit. Re-test after proxy-plan, gateway, operating-system, runtime, library or regional infrastructure changes.

TCP keepalive settings can support dead-peer detection, but treat them as a separate experiment. Confirm whether probes traverse the complete path and whether the application receives failure early enough. Keepalive should not be used to hold unnecessary connections open indefinitely.

Design a safe retry policy

Retry only when all conditions are met:

  • the operation is idempotent or carries an approved idempotency control;
  • the failure occurred before an ambiguous application commit;
  • the stale connection is removed from the pool;
  • the new attempt uses a fresh connection;
  • a strict attempt budget, backoff and jitter are enforced;
  • total deadline and cost remain within policy.

Never send the same non-idempotent request repeatedly merely because the first response was missing. “No response received” does not prove “the origin did nothing.”

Metrics and alerting

Track by provider, route class, market, address family and protocol:

  • validated reuse success rate by idle-gap bucket;
  • clean-retirement rate;
  • stale-reuse failure rate;
  • fresh-connection fallback rate;
  • retries per useful result;
  • p50 and p95 time to useful result;
  • connection age at failure;
  • sockets and handles after the test window;
  • sticky-session continuity and unexpected exit rotation.

Alert on a boundary shift, not just on total failures. A safe window falling from minutes to seconds can increase handshake load and tail latency before the overall success rate looks alarming.

Acceptance checklist

  • [ ] Every timeout and owner is documented.
  • [ ] Fixtures are owned or explicitly authorized and deterministic.
  • [ ] Direct and proxy tests use the same client settings.
  • [ ] Idle gaps cover both common and boundary conditions.
  • [ ] Reuse and fresh reconnection are measured separately.
  • [ ] Response digest and semantic completion are verified.
  • [ ] HTTP/1.1 and multiplexed protocols are classified correctly.
  • [ ] IPv4, IPv6, route class and required markets are sampled.
  • [ ] Client retirement includes a conservative safety margin.
  • [ ] Retries are safe, bounded and use fresh connections.
  • [ ] Socket, handle and memory recovery are checked.
  • [ ] Evidence contains no secrets or unnecessary personal data.

FAQ

Is HTTP keep-alive the same as TCP keepalive?

No. HTTP persistence allows multiple requests on a connection. TCP keepalive uses transport probes to detect an unresponsive peer. Their controls and failure signals are different.

Should the client idle timeout equal the proxy timeout?

No. Retire client connections before the lowest reliable intermediary boundary and include a margin. Equal values create a race at the worst possible moment.

Does opening a new connection after every request solve the problem?

It avoids stale reuse but adds handshakes, latency and resource cost. Measure whether conservative pooling can remain correct before disabling reuse globally.

Can a successful retry hide stale-connection failures?

Yes. Report the first-attempt failure, fresh-connection fallback and final useful result separately. Otherwise retry amplification remains invisible.

Compliance and safe operation

Use only authorized accounts, destinations, data and markets. Respect access controls, privacy requirements, platform terms and rate limits. Do not keep connections alive to evade session policies or access restrictions. Protect credentials, keep TLS verification enabled and minimize retained evidence.

Continue with the proxy response-integrity test, residential proxy session-stickiness test, and Node.js proxy-client canary plan.

Standards basis: RFC Editor, HTTP Semantics and HTTP/1.1, June 2022; Transmission Control Protocol, August 2022. Reviewed September 12, 2026.