HTTP caching is one of the most powerful yet misunderstood aspects of web performance. Done right, it can make your website feel instant. Done wrong, it can cause stale content, broken updates, and confused users.
The Cache-Control Header
This is the most important caching header. It tells browsers and CDNs exactly how to handle your content. For static assets that never change without a URL change, immutable combined with a long max-age is the gold standard:
Cache-Control: public, max-age=31536000, immutable
The immutable directive is a promise: this resource will not change during its cache lifetime. Browsers that support it will never send conditional requests, saving precious milliseconds.
Conditional Validation
For dynamic content like blog posts or user profiles, you want a different strategy. Set max-age=0, must-revalidate and provide either an ETag or Last-Modified header. This way, the browser always checks with the server, but if nothing changed, the server replies with a lightweight 304 Not Modified instead of the full response body.
"Caching is not about preventing requests—it's about making the right requests at the right time."
Common Mistakes
One of the biggest mistakes is using HTML <meta http-equiv> tags for caching. These almost always conflict with proper HTTP headers and should be avoided entirely. Always set caching policies via HTTP headers in your server configuration or application code.
Private vs Public
Remember that public means shared caches (like CDNs) can store the response, while private restricts caching to the end user's browser. Never mark authenticated or user-specific content as public unless you want it cached by a CDN and served to other users!