← Back to Apache Course | Chapter 5: Performance | Lesson 1 of 4

KeepAlive

KeepAlive lets a browser reuse a single connection for multiple requests to the same server, instead of opening a brand new connection for every single file -- which matters a lot on a page that loads dozens of images, scripts, and stylesheets.

Why Reusing Connections Matters

Opening a TCP connection (and, for HTTPS, completing a TLS handshake on top of it) has real overhead. A page with 40 assets that opened a fresh connection for every one of them would pay that cost 40 times over. KeepAlive keeps the connection open after a response so the next request can reuse it immediately.

The Directives

KeepAlive On turns the feature on (it's on by default in modern Apache). MaxKeepAliveRequests caps how many requests can be served on one connection before it's closed (0 means unlimited). KeepAliveTimeout sets how many seconds Apache waits for another request on an idle connection before closing it.

The Trade-off

A longer KeepAliveTimeout helps a browser reuse connections across several page assets, but every kept-alive connection ties up a worker/thread waiting, even when it's doing nothing. On a busy server, a timeout that's too long can exhaust available workers under high traffic; a value that's too short defeats the point of KeepAlive in the first place.

Note: A KeepAliveTimeout between 2-5 seconds is a common, sensible starting point for most sites -- long enough to catch a page's remaining assets, short enough not to hold connections open needlessly.

How It Interacts with the MPM

How costly a long KeepAliveTimeout is depends heavily on which Multi-Processing Module (MPM) is in use -- covered in the next lesson. The prefork MPM ties up a whole process per kept-alive connection, making a long timeout expensive; event was specifically designed to handle keep-alive connections far more efficiently.

Example: A sensible KeepAlive configuration

apacheconf
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5
{# Flagged by hand after confirming a runner can't handle this example (a shell command / go.mod file stored as a TopicExample, a language feature the configured runner version doesn't support, or output that blows a runner's sandbox limit) -- see TopicExample.norun. Never render the run button for these, regardless of language, since it would just fail at execute_code (or worse, hang the Judge0 queue on a submission that can never finish cleanly). #}

⚠️ This example can't run in the browser editor. Try it in your own local environment instead.

{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Setting KeepAliveTimeout very high (30+ seconds) on a busy server, tying up workers on idle connections and reducing how many concurrent visitors the server can actually serve.
  2. Disabling KeepAlive entirely to "simplify" things, which usually makes real-world page loads slower since every asset now needs its own new connection.
  3. Tuning KeepAliveTimeout without considering which MPM is active -- the same value has very different costs under prefork versus event.
🔒

Chapter Quiz — Complete all 4 topics to unlock

0/4 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.