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.

Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
Mastering HTTP Caching: From Expires to ETag and Browser Refresh Strategies

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: Pragma and Expires. Although largely obsolete, they are still seen for backward compatibility.

Pragma

If Pragma: no-cache is present, the client must revalidate the resource on every request. This header has higher priority than Cache-Control.

Cache-Control: public, max-age=86400
Pragma: no-cache

Expires

Expires

specifies 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.

Expires: Fri, 11 Jun 2021 11:33:01 GMT

Cache‑Control (HTTP/1.1)

HTTP/1.1 introduced Cache-Control to define freshness using relative time intervals, solving the clock‑sync issue of Expires. When both Expires and Cache-Control appear, Cache-Control wins. The priority order is Pragma → Cache‑Control → Expires .

Typical directives include:

max-age
no-cache
must-revalidate
Cache-Control: max-age=3600, must-revalidate

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 Modified and no body.

Last-Modified: Fri, 22 Jul 2016 01:47:00 GMT

ETag

The server generates a unique identifier (e.g., an MD5 hash) for the resource and returns it in the ETag header. The client includes this value in If-None-Match. A matching ETag also results in a 304 response.

ETag: "5d8c72a5edda8d6a:3239"

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=0 and If-Modified-Since (or If-None-Match) to validate freshness. A 304 response is typical.

Press Ctrl+F5 – the browser bypasses all caches, sending no validation headers, resulting in a full 200 response with the resource.

Caching Practice

In real projects, it is common to send both Expires and Cache‑Control for maximum compatibility, and to include either Last‑Modified or 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 Expires for HTTP/1.0 compatibility; otherwise prefer Cache‑Control.

Choose ETag when you need sub‑second change detection; otherwise Last‑Modified is sufficient.

Combine a freshness header ( Expires or Cache‑Control) with a validation header ( Last‑Modified or 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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

cachingWeb PerformanceCache-ControlETag
Tencent IMWeb Frontend Team
Written by

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.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.