How to Enable Keep-Alive Connections in Apache

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

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:

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:

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

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

Security Best Practices

RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500

Performance Optimization Tips

sudo a2enmod http2
Protocols h2 h2c http/1.1

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

Exit mobile version