Mastering HTTP Caching: From Expires to ETag and Browser Refresh Strategies
This article explains the essential HTTP caching headers—Expires, Cache‑Control, Pragma, Last‑Modified, and ETag—their priorities, how browsers validate cached resources, and the impact of different refresh actions (URI entry, F5, Ctrl+F5) on cache behavior, offering practical guidance for optimal web performance.
Introduction
Fetching content over the network is slow and costly because large responses require multiple round‑trips between client and server, delaying when the browser can use the data and increasing data costs for visitors. Therefore, caching and reusing previously fetched resources is a key performance optimization.
HTTP Header Fields Related to Caching
The RFC2616 specification defines 47 HTTP header fields, of which several are directly related to caching. They can be grouped into four categories:
General headers
Request headers
Response headers
Entity headers
Stone Age Caching (HTTP/1.0)
In the HTTP/1.0 era, caching was controlled by two headers:
Pragmaand
Expires. Although largely obsolete, they are still seen for backward compatibility.
Pragma
If
Pragma: no-cacheis present, the client must revalidate the resource on every request. This header has higher priority than
Cache-Control.
<code>Cache-Control: public, max-age=86400
Pragma: no-cache</code>Expires
Expiresspecifies an absolute GMT date after which the resource is considered stale. If the client’s clock differs from the server’s, the expiration may be inaccurate.
<code>Expires: Fri, 11 Jun 2021 11:33:01 GMT</code>Cache‑Control (HTTP/1.1)
HTTP/1.1 introduced
Cache-Controlto define freshness using relative time intervals, solving the clock‑sync issue of
Expires. When both
Expiresand
Cache-Controlappear,
Cache-Controlwins. The priority order is Pragma → Cache‑Control → Expires .
Typical directives include:
max-age no-cache must-revalidate <code>Cache-Control: max-age=3600, must-revalidate</code>Validation Headers
Last‑Modified
The server returns the last modification time of the resource. The client sends it back in
If-Modified-Since. If unchanged, the server replies with
304 Not Modifiedand no body.
<code>Last-Modified: Fri, 22 Jul 2016 01:47:00 GMT</code>ETag
The server generates a unique identifier (e.g., an MD5 hash) for the resource and returns it in the
ETagheader. The client includes this value in
If-None-Match. A matching ETag also results in a
304response.
<code>ETag: "5d8c72a5edda8d6a:3239"</code>Header Comparison
Expires : simple, uses absolute time, vulnerable to client‑server clock differences.
Cache‑Control : uses relative time, richer options, but only supported by HTTP/1.1.
Last‑Modified : avoids version issues, but any file change triggers a fresh response even if content is unchanged.
ETag : most precise, can detect multiple changes within a second, but adds computational overhead and requires consistent generation across distributed servers.
User Refresh / Access Behaviors
Three common ways to reload a page have different cache effects:
Enter URL in the address bar and press Enter – the browser may serve the resource from cache without contacting the server if it is still fresh.
Press F5 or click the refresh button – the browser forces a request, adding
Cache-Control: max-age=0and
If-Modified-Since(or
If-None-Match) to validate freshness. A
304response is typical.
Press Ctrl+F5 – the browser bypasses all caches, sending no validation headers, resulting in a full
200response with the resource.
Caching Practice
In real projects, it is common to send both
Expiresand
Cache‑Controlfor maximum compatibility, and to include either
Last‑Modifiedor
ETag(or both) for validation.
Static assets are often versioned (e.g., by appending an MD5 hash to the filename or query string) so that a change automatically creates a new URL, forcing browsers to fetch the updated file while allowing long cache lifetimes for unchanged assets.
Conclusion
Use
Expiresfor HTTP/1.0 compatibility; otherwise prefer
Cache‑Control.
Choose
ETagwhen you need sub‑second change detection; otherwise
Last‑Modifiedis sufficient.
Combine a freshness header (
Expiresor
Cache‑Control) with a validation header (
Last‑Modifiedor
ETag) for robust caching.
Version static files to extend cache lifetimes while ensuring updates are fetched.
References
Various articles and documentation on browser HTTP caching, Last‑Modified, ETag, Expires, Cache‑Control, and refresh behavior.
Tencent IMWeb Frontend Team
IMWeb Frontend Community gathering frontend development enthusiasts. Follow us for refined live courses by top experts, cutting‑edge technical posts, and to sharpen your frontend skills.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.