Apache Keep-Alive Tuning: Reduce Latency by Reusing TCP Connections
Persistent connections cut handshake overhead, but default timeout and worker limits can hurt more than help. Here's how to tune Keep-Alive for real latency gains.
06 Dec 2025, 14:37 UTC

The problem: every request pays a handshake cost
\nWhen Keep-Alive is off, Apache closes the TCP connection after each HTTP response. The next request forces a full three-way handshake, adding round-trip latency especially on high-latency networks or mobile clients. On a busy server, this multiplies across thousands of requests.
\n\nHow Keep-Alive works
\nKeep-Alive is an Apache directive that tells the server to leave the TCP connection open after a response. Subsequent requests can reuse the same connection, skipping the handshake. This is especially effective for static assets, API endpoints, or any workload with repeated calls to the same host.
\n\nDefault settings and what to watch
\nApache 2.4 ships with KeepAlive On enabled by default. The timeout defaults to KeepAliveTimeout 5, balancing reuse with resource retention. There's also MaxKeepAliveRequests, which limits how many requests can ride a single connection before Apache closes it (unlimited by default). Finally, MaxRequestWorkers must be set high enough to handle the extra connections that persistent connections create, otherwise you'll see workers exhausted under load.
- \n
KeepAliveTimeout 5– seconds to wait for the next request on an idle connection \n MaxKeepAliveRequests unlimited– requests per connection before closure \n MaxRequestWorkers– maximum simultaneous child processes; tune to expected concurrent persistent connections \n
Worked example: measuring the gain
\nUse wrk or ab to compare latency with Keep-Alive on and off. Run the command on any machine that can reach your Apache host:
# Where: a client machine with network access to Apache\n# Permissions: unprivileged user; wrk does not require root\n# Placeholder: replace http://localhost:8080/api/status with your target URL\nwrk -t2 -c100 -d30s http://localhost:8080/api/status\nWhile the test runs, monitor server state (requires mod_status):
serverctl status | grep "Busy workers"\nserverctl status | grep "Idle workers"\nExpected checks: Compare average and 95th-percentile latency between runs; observe whether "Idle workers" remain stable or "Busy workers" decrease faster when Keep-Alive is off.
\nRelevant risks: Without tuning MaxRequestWorkers and KeepAliveTimeout, high concurrency with persistent connections can deplete available workers, increasing request queueing latency. Start with conservative settings and adjust based on observed metrics.
Trade-off: resource retention vs handshake savings
\nKeeping connections open consumes file descriptors and worker slots. If many clients open persistent connections and never reuse them, or if the timeout is too long, Apache can accumulate idle-but-held connections, driving up "Busy workers" and reducing capacity for new requests. Setting MaxKeepAliveRequests to a finite number (e.g., 100) caps connection lifespan, and matching KeepAliveTimeout to your typical round-trip time (often 2–4 seconds on local networks) prevents excess retention.
Actionable checklist
\n- \n
- Ensure
KeepAlive Onis present inhttpd.conf(or default in Apache 2.4+) \n - Set
KeepAliveTimeoutto your network's round-trip time (start with 2–5) \n - Assign a finite
MaxKeepAliveRequestsif you see connection bloat \n - Adjust
MaxRequestWorkersto accommodate expected concurrent persistent connections \n - Re-benchmark with your real workload and verify latency improvement \n
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.