How to Enable Keep-Alive Connections in Apache

How to enable Keep-Alive connections in Apache

Somewhere early in my server administration journey, I noticed my site’s pages loading noticeably faster after I made one small config change: enabling Keep-Alive. It seemed almost too simple to matter, but the reduction in latency, especially for pages loading multiple CSS, JS, and image files, was immediately obvious in browser dev tools.

What Is Keep-Alive, and Why Does It Matter?

By default, HTTP/1.0 opened a brand new TCP connection for every single request — one for the HTML, another for each CSS file, another for each image, and so on. Establishing a TCP connection involves a handshake (and, for HTTPS, a TLS handshake too), which adds real, measurable latency, especially for visitors physically far from your server.

Keep-Alive (formally “persistent connections”) lets a single TCP connection be reused for multiple requests, avoiding the overhead of repeated handshakes. For a typical webpage loading a dozen or more assets, this can make a substantial difference in total load time.

HTTP/1.1 actually defaults to persistent connections, but Apache still gives you control over how long those connections stay open and how many requests each one can handle.

Prerequisites

  • Apache installed with root/sudo access.
  • Ability to test your site’s load times before and after (I’ll show you how using browser dev tools and curl).

Step 1: Check Whether Keep-Alive Is Currently Enabled

apache2ctl -M | grep -i keepalive

That won’t directly tell you if it’s enabled, since Keep-Alive isn’t a separate module — it’s a core Apache feature. Instead, check your configuration directly:

grep -i keepalive /etc/apache2/apache2.conf

Or test it directly against a live response:

curl -I --http1.1 https://example.com

Look for a Connection: keep-alive header in the response.

Step 2: Enable Keep-Alive

Open your main Apache configuration file:

sudo nano /etc/apache2/apache2.conf

(On CentOS/RHEL, this is usually /etc/httpd/conf/httpd.conf.)

Add or update these directives:

KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5

Let me explain each:

  • KeepAlive On: Turns the feature on. This is the master switch.
  • MaxKeepAliveRequests: The maximum number of requests allowed on a single persistent connection before Apache closes it. Setting this to 0 allows unlimited requests per connection, though I generally recommend a reasonable cap like 100.
  • KeepAliveTimeout: How many seconds Apache waits for a subsequent request on an already-open connection before closing it. This is the setting that requires the most thought (more on that below).

Step 3: Test Your Configuration and Restart

sudo apache2ctl configtest
sudo systemctl restart apache2

Verify again with curl:

curl -I --http1.1 https://example.com

You should now see Connection: Keep-Alive and, in verbose mode (curl -v), evidence that a single connection handles multiple requests when fetching several assets.

Step 4: Tune KeepAliveTimeout Carefully

This is the setting I’ve adjusted the most over the years, because it directly trades off between two competing goals:

  • Higher timeout: Better for visitors on slow connections making multiple sequential requests (fewer new handshakes needed). But it also means more threads/processes sit idle, waiting for a follow-up request that may never come. – Lower timeout: Frees up server resources faster, letting Apache serve more concurrent visitors. But it can force more visitors into fresh TCP handshakes for each new asset request if they’re slow to send follow-up requests.

The default Apache value has historically been 5 seconds, and honestly, I rarely stray far from that. On low-traffic personal sites, I’ve bumped it to 10-15 seconds without any noticeable downside. On high-traffic servers where I’m carefully managing worker/thread limits (see my dedicated Apache tuning post), I actually prefer to keep it at 2-3 seconds, or even use Event MPM which handles idle Keep-Alive connections far more efficiently than Prefork ever could.

KeepAliveTimeout 3

Step 5: Combine with Event MPM for Best Results

This is worth calling out specifically: if you’re running Prefork MPM, every Keep-Alive connection ties up an entire process, even while idle, waiting for a possible follow-up request. This can quickly exhaust your MaxRequestWorkers limit under moderate traffic.

Event MPM was specifically designed to solve this problem — it uses a dedicated thread to manage idle Keep-Alive connections separately from the threads actually processing requests, freeing up worker threads much more efficiently.

sudo a2dismod mpm_prefork
sudo a2enmod mpm_event
sudo systemctl restart apache2

If you’re stuck on Prefork due to legacy module requirements, keeping KeepAliveTimeout low (2-3 seconds) becomes much more important to avoid resource exhaustion.

Real-World Use Cases

  • Content-heavy websites: Pages loading many images, stylesheets, and scripts benefit enormously from connection reuse.
  • Mobile visitors on higher-latency connections: Avoiding repeated TCP/TLS handshakes matters even more when round-trip time is already high.
  • API servers with chatty clients: Applications making multiple sequential API calls benefit from not re-establishing a connection each time.
  • High-concurrency servers: Careful tuning here directly affects how many simultaneous visitors your server can comfortably support.

Troubleshooting Common Issues

Problem: Server becomes unresponsive under moderate traffic after enabling Keep-Alive. This usually means you’re on Prefork MPM with a KeepAliveTimeout set too high, exhausting available worker processes. Lower the timeout or switch to Event MPM.

Problem: Keep-Alive doesn’t seem to be working (new connection for every request). Check for a reverse proxy or CDN in front of your server that might be terminating connections and reopening simple HTTP/1.0-style requests without keep-alive to the origin server. Also confirm KeepAlive On is actually set — a mistyped directive fails silently in some Apache versions.

Problem: Load testing tools show worse performance with Keep-Alive enabled. Some load testing tools open a new connection per simulated request by design, which doesn’t reflect real browser behavior. Make sure your testing methodology actually simulates persistent connections if you want representative results.

Common Mistakes to Avoid

  • Setting KeepAliveTimeout extremely high (like 60+ seconds) on a Prefork-based server, quickly exhausting available worker processes.
  • Assuming Keep-Alive is “on” by default without verifying — some hardened server configurations or specific distributions ship with it disabled.
  • Not considering the MPM in use when tuning Keep-Alive settings — the “right” timeout value depends heavily on whether you’re using Prefork or Event MPM.
  • Forgetting that a reverse proxy or CDN in front of Apache may negotiate its own Keep-Alive behavior independently, requiring you to check both layers.

Security Best Practices

  • Pair reasonable KeepAliveTimeout values with an appropriate Timeout directive to prevent slow-loris style attacks where a client opens connections and sends data extremely slowly to exhaust server resources.
  • Consider mod_reqtimeout alongside Keep-Alive tuning for additional protection against slow-request attacks:
RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500
  • Monitor connection counts during traffic spikes to detect potential abuse patterns exploiting persistent connections.

Performance Optimization Tips

  • Combine Keep-Alive with HTTP/2 (mod_http2) for even greater efficiency — HTTP/2 multiplexes multiple requests over a single connection natively, building on the same underlying idea as Keep-Alive but far more effectively:
sudo a2enmod http2
Protocols h2 h2c http/1.1
  • Use Event MPM rather than Prefork whenever possible, since it handles the resource cost of Keep-Alive connections far more gracefully.
  • Reduce the number of separate assets your pages load (combining CSS/JS files, using image sprites or modern formats) so the benefit of Keep-Alive compounds with fewer, more efficient requests overall.

Frequently Asked Questions

Is Keep-Alive on by default in Apache? It’s typically enabled by default in standard Apache installations, but some distributions or hardened configurations disable it, so it’s worth verifying explicitly.

What’s a good KeepAliveTimeout value? Apache’s traditional default of 5 seconds works well for most use cases. I personally lean toward 2-3 seconds on high-traffic Prefork servers, and I’m comfortable going up to 10-15 seconds on low-traffic servers running Event MPM.

Does Keep-Alive affect HTTPS sites more than HTTP sites? Yes, arguably even more — the TLS handshake avoided by reusing a connection is more expensive than the plain TCP handshake, so the latency savings are actually larger for HTTPS.

Should I disable Keep-Alive on a very low-traffic personal server? Generally no — even a single visitor benefits from faster page loads through connection reuse, and low traffic means resource exhaustion isn’t a real concern in the first place.

Summary and Key Takeaways

Keep-Alive is a small setting with an outsized impact on real-world page load performance, since it eliminates repeated connection handshake overhead for pages loading multiple assets.

The essentials to remember:

  1. Enable it explicitly with KeepAlive On if it isn’t already.
  2. Set MaxKeepAliveRequests to a reasonable cap (100 is a solid default).
  3. Tune KeepAliveTimeout based on your MPM and traffic patterns — lower on Prefork/high-traffic servers, more relaxed on Event MPM/low-traffic servers.
  4. Pair Keep-Alive with Event MPM and, ideally, HTTP/2 for the best combination of performance and resource efficiency.
  5. Guard against slow-request attacks with mod_reqtimeout alongside your Keep-Alive configuration.

It’s one of those settings that takes five minutes to configure properly but pays dividends in every single page load afterward.

References

Total
1
Shares

Leave a Reply

Previous Post
How to set up caching in Apache

How to Set Up Caching in Apache

Next Post
How to use Apache's mod_rewrite for URL rewriting

How to Use Apache’s mod_rewrite for URL Rewriting

Related Posts