Performance Basics
Web Servers Fundamentals
Chapter 9 · Performance Basics
Chapter 2 compared how each server handles many connections at once, and Chapter 6 mentioned caching in passing as one reason to reverse-proxy a single backend. This chapter covers three concrete performance techniques any of the three servers can apply, largely independent of the architecture debates earlier chapters focused on — and where each one can actually backfire if applied without thinking about what it's doing.
Keep-Alive Connections
Opening a new TCP connection (and, over HTTPS, repeating the TLS handshake from Chapter 7) for every single request is expensive. Keep-alive reuses one already-open connection for multiple requests instead, avoiding that repeated setup cost. Apache controls this with KeepAlive, KeepAliveTimeout, and MaxKeepAliveRequests; Nginx with keepalive_timeout and keepalive_requests; IIS through its own connection timeout settings in IIS Manager. All three enable keep-alive by default today — the main tuning question is how long to hold an idle connection open before closing it, trading a small amount of held-open resources against avoiding a future reconnection cost.
Compression
Compressing a response body (typically with gzip, or the newer and generally more efficient brotli) before sending it trades a small amount of server CPU time for meaningfully fewer bytes sent over the network — usually a clear win for text-based content like HTML, CSS, and JavaScript. Apache enables this via mod_deflate; Nginx via its gzip directive plus a gzip_types list naming which content types to compress; IIS through its Dynamic Content Compression and Static Content Compression settings in IIS Manager.
Caching
Caching happens at two different levels. Browser caching uses response headers like Cache-Control and Expires to tell the browser it can reuse a previously downloaded asset without re-requesting it at all for some period of time — set directly by the web server for static files. Server-side or proxy caching — Chapter 6's own caching mention, revisited here — stores a copy of a response on the server or reverse proxy itself, so a subsequent identical request can be answered from that stored copy without hitting the backend application again at all. Apache offers this via mod_cache; Nginx via proxy_cache; IIS via its own Output Caching feature.
| Apache | Nginx | IIS | |
|---|---|---|---|
| Keep-alive | KeepAlive/KeepAliveTimeout | keepalive_timeout/keepalive_requests | Connection timeout settings (IIS Manager) |
| Compression | mod_deflate | gzip/gzip_types | Dynamic/Static Content Compression |
| Server-side caching | mod_cache | proxy_cache | Output Caching |
Hands-On Exercises
Write the Nginx directives that enable gzip compression for text/css, application/javascript, and text/html content.
📄 View solutionA team enables gzip compression for every content type on their server, including .jpg and .mp4 files. Explain, using this chapter's own warning box, why this is unlikely to help and may actually make things slightly worse.
📄 View solutionA site enables server-side/proxy caching for a page that shows each logged-in user their own account dashboard, using the URL alone as the cache key. Explain what could go wrong, and why this is a more serious problem than a typical performance misconfiguration.
📄 View solutionChapter 9 Quick Reference
- Keep-alive — reuse one TCP/TLS connection for multiple requests, avoiding repeated handshake overhead
- Compression (gzip/brotli) — trades server CPU for fewer bytes over the wire; a clear win for text, not for already-compressed binary content
- Browser caching (Cache-Control/Expires) vs. server-side/proxy caching (Chapter 6 revisited) — two different levels solving two different problems
- Caching dynamic/personalized content incorrectly can leak one user's data to another — a real security bug, not just a performance issue