LEARN VISUALLY · Web basics

HTTP caching: reuse, validate or fetch again?Explained visually

Distinguish a fresh cached response, a stale response requiring validation, and the different meanings of no-cache and no-store.

An unchanged lesson does not always need to be downloaded again. A cache may reuse an eligible response or ask the origin whether it changed. The important question is whether reuse is allowed now, not merely whether an old copy exists.

Jump to a section
Branches represent decisions, not a guaranteed path for every request. Stale reuse exceptions are omitted. Request arrives: Is a stored response eligible?. Fresh copy: May reuse under cache rules. Stale copy: Validate when required. Origin check: Unchanged: 304; changed: new body. Stored response: Update metadata or replace content
Branches represent decisions, not a guaranteed path for every request. Stale reuse exceptions are omitted.

The diagram’s relationships are explained in the readable cards below. Open the full-size SVG to zoom.

Download branded diagram (SVG)

Read the diagram

Branches represent decisions, not a guaranteed path for every request. Stale reuse exceptions are omitted.

01 · Diagram relationship

Request arrives

Is a stored response eligible?

02 · Diagram relationship

Fresh copy

May reuse under cache rules

03 · Diagram relationship

Stale copy

Validate when required

04 · Diagram relationship

Origin check

Unchanged: 304; changed: new body

05 · Diagram relationship

Stored response

Update metadata or replace content

What you will learn

Distinguish a fresh cached response, a stale response requiring validation, and the different meanings of no-cache and no-store.

Prerequisites: comfortable reading a web address. No programming is required for the explanation.

Freshness has a clock

For the simplified fixture assume an otherwise cacheable response has max-age=60 and age starts at zero. At age 59 it is fresh; at age 60 it is stale. Real HTTP age calculations include response age and time spent in caches; they are not just a timer since the browser last opened the page.

Validate a stored copy

An origin can attach an ETag validator. A client may send If-None-Match with a stored validator. When appropriate, a 304 response lets it reuse the stored representation with updated metadata. A 304 is not a newly downloaded JSON body. If the representation changed, a normal response can carry replacement content.

Read the directives literally

no-cache permits storage but requires successful validation before reuse under its rules. no-store instructs caches not to store the response; it is not a remote eraser for copies already retained elsewhere. private restricts shared-cache storage. These directives solve different problems.

Respect the application context

Personalized content needs careful cache policy and cache-key design. A URL alone may not capture all request variations. Our public lesson fixture excludes authentication, Vary, shared-cache interactions and stale-serving extensions. A cache hit does not establish that the data is correct.

Start with the copy the reader is actually seeing

Imagine a reader opens a public lesson, returns a little later, and sees the same wording without a full download. That can be useful: a stored response may save a round trip or avoid transferring the representation again. Now imagine an editor corrected an important paragraph between those visits. Reuse becomes a policy question. The relevant decision is not simply whether an old copy exists, but whether that copy may satisfy this request now or needs checking with the origin first.

Our fictional lesson service provides a small public JSON representation. It has no account-specific content, and we assume it is otherwise eligible for caching. These assumptions let us examine freshness and validation without pretending to supply a production policy for private data. We will use a short freshness lifetime and an ETag in a local model. The example's elapsed times are arithmetic inputs, not measurements of a browser, CDN or deployed website.

A useful cache diagram has a decision in it. If a stored response is eligible and fresh under the applicable rules, it may be reused. If it is stale, validation may be required before reuse. If it cannot be reused or validation reports a change, another representation is needed. The diagram should not suggest that every request must pass through a fresh state, a stale state and a 304 in sequence. Those are different possible outcomes, not a fixed itinerary.

Keep the stored representation and its rules together

A cache needs more than a file containing old content. It also needs information for deciding which request that response can serve and under what conditions. Response metadata can describe freshness and validators. Request characteristics can affect matching. If you think only about the stored body, it becomes difficult to explain why two apparently similar visits produce different network behavior or why a response can be stored but still require a check before reuse.

For our fictional public lesson, imagine the origin supplies Cache-Control: max-age=60 and ETag: "lesson-v1". We will start the model's age at zero and omit real age calculations for clarity. The lifetime expresses a reuse rule; the ETag is a validator supplied by the origin. They answer different questions. The lifetime helps decide whether the stored response is fresh. The validator can help ask whether the selected representation has changed when a check is needed.

Do not assume the ETag is a content hash that your client should calculate independently. The service chooses and interprets its validators under the relevant HTTP rules. In a teaching fixture, short values such as "lesson-v1" make comparisons readable. In an actual client, treat the received value according to the protocol and service behavior rather than inferring a hidden version numbering scheme. A readable validator is not a promise that every resource uses the same format or update strategy.

Walk through the freshness boundary

At time zero, our cache stores the lesson response with the simplified lifetime of 60 seconds. At age 20, it has 40 seconds left in this model. At age 59, it is fresh with one second remaining. At age 60, it is stale because the lifetime is no longer greater than the current age. That exact boundary is a useful test: code that treats age equal to lifetime as fresh changes the modeled behavior by a full boundary case.

Real HTTP age is not always a stopwatch that begins when a tab first opens. Responses may already have age from time spent in caches, and dates and transfer timing can matter. A reader who sees max-age=60 should not conclude that every recipient receives 60 entirely new seconds. Our local arithmetic intentionally assumes age starts at zero. Keep the assumption attached to the example so a simple lesson does not become an incorrect production formula.

Now suppose the origin changes the lesson at time 25 while the cache still has a fresh stored response. The origin's edit does not, by itself, replace that stored body everywhere. Reuse is governed by the cache rules and any invalidation mechanisms the system actually implements. This is the trade-off the editor needs to understand: allowing reuse can reduce work and delay, but it can also allow an older eligible representation to remain visible for some period.

Validate without pretending to download the body again

When validation is appropriate, our client sends a conditional request containing If-None-Match: "lesson-v1". If the relevant representation has not changed and the condition is handled accordingly, a 304 response tells the cache that it can use its stored representation with the appropriate metadata updates. The 304 is not a second copy of the lesson's JSON body. This distinction explains how a request can reach the origin without retransferring the entire representation.

If the selected representation has changed, the service can return a normal response containing the newer body and its metadata. Our fixture calls that newer validator "lesson-v2". The cache replaces or updates its stored information as appropriate. The client should not append the new response to the old JSON or treat a missing 304 body as a parsing failure. It needs to interpret the conditional exchange in the context of the representation it already holds.

Try telling this story from the reader's perspective. In the unchanged case, the reader sees the lesson again after a successful check, while the network transfers less representation content. In the changed case, the reader gets the corrected lesson. These are different paths to a useful result. Counting every network request as a full cache miss or every unchanged screen as an unchecked cache hit loses the information that validation provides. Inspect the exchange before assigning those labels.

Read directives by what they allow

The names no-cache and no-store are easy to confuse. A response marked no-cache can be stored, but reuse requires successful validation under its rules. A response marked no-store instructs caches not to store it. The difference is practical: one policy can retain a representation for later checking, while the other prohibits that storage. Neither name should be paraphrased as simply turn caching off without explaining which behavior is meant.

The private directive restricts storage by shared caches; it is not a general certificate that content is secret or that every device has erased prior copies. Likewise, no-store is not a remote deletion command for information already retained elsewhere. If the problem is that sensitive information was exposed, selecting a cache directive afterward is only one possible part of a broader response. Do not promise erasure or confidentiality based on a header whose scope is narrower than that promise.

For the public lesson scenario, the editor can compare policies in terms of acceptable reuse and update delay. For an account-specific page, the design must also consider who is allowed to receive the representation, which requests are distinguished, and which caches may hold it. This lesson does not prescribe headers for every authenticated application. The safe takeaway is to identify the actual audience and reuse requirements before borrowing a public-content example for a private workflow.

A URL alone may not identify every reusable variant

Suppose the fictional service can return an English lesson or another language at the same path depending on request information. A cache must not serve an arbitrary stored variant just because the path matches. HTTP provides mechanisms such as Vary to indicate relevant request fields, and a real deployment needs correct cache-key and representation behavior. The example illustrates why matching matters; it does not claim that adding one header automatically repairs every configuration.

Write the product requirement before the cache rule. If language is chosen in the URL, the two addresses already differ in that respect. If it is chosen through a request field, the system must distinguish those variants through the applicable mechanism. If it is personal account data, additional constraints apply. Treating all three cases as a generic page cache hides the very inputs needed to keep responses appropriate. The cache should support the application contract rather than accidentally redefine it.

Use a controlled comparison when investigating a suspected mismatch. Record the exact request, relevant fields, returned representation and observed cache metadata without exposing private data. Change only the variant input you are investigating. A successful reload with cache disabled may be a useful clue, but it does not identify which key, metadata rule or intermediate cache was responsible. Preserve enough evidence to ask the next specific question instead of declaring all caching unreliable.

Choose a policy by the cost of being old

Consider three fictional resources: an immutable illustration named with a version, a public lesson that receives occasional corrections, and a private saved-reading-list response. They need not share one caching policy. The illustration can have a new URL when its content changes. The lesson needs a deliberate balance between reuse and correction visibility. The private response needs a design that respects its audience and data exposure. Those are product requirements before they are header values.

For the lesson, ask how quickly a correction must become visible, how expensive a validation is, and what happens during an origin failure. The acceptable answer for a minor wording change may differ from the answer for a safety-critical correction. Document the choice and test representative outcomes. Do not select an aggressive freshness lifetime merely because it makes a speed score look better, then discover that the editorial workflow has no reliable way to distribute an important change.

Versioned asset names can help avoid one class of confusion: a revised diagram can receive a different URL while old pages continue referring to the old asset. That approach has deployment and storage consequences and does not replace correct caching of the HTML that references it. The lesson here is to reason about the whole update chain. A fresh asset is not useful if the page still points at the previous filename, and a changed page is not enough if the served asset remains inconsistent.

Diagnose the stale lesson without guessing

A reader reports seeing the old paragraph after an edit. First confirm the exact URL and expected new content. Check whether the origin actually serves that edition before changing cache settings. If the origin is correct, inspect the response and any observed cache information along a permitted test path. Distinguish a stored browser response, a shared intermediary and application-level saved data where evidence allows. Do not assume that every old screen is an HTTP cache problem.

Our own fictional app could store a lesson object in memory after loading it. Even if a later HTTP request returns the updated body, the interface might continue rendering the older object because its state was not replaced. That is an application update failure. A database could also contain an old edition, making the response correct for the data actually deployed but wrong for the editor's expectation. Both cases show why the first check should compare actual content at each boundary.

Write a small incident note: expected edition, observed edition, request path, relevant metadata, time, and the smallest controlled change that alters the result. Avoid recording private headers or account content in public evidence. If clearing one local store resolves the symptom, state exactly what was cleared and what you observed afterward. Do not turn one successful refresh into the claim that every reader worldwide now sees the corrected lesson or that the underlying policy has been fully verified.

Practice: choose the next action

Our synthetic response has lifetime 60 and current age 59. With all other reuse conditions satisfied and no extra request constraints, it is fresh in the model. At age 60, it is stale. If its validator still matches the origin, the conditional path can produce a 304 and reuse of the stored body. If the validator no longer matches, the replacement path can provide a new body. State those outcomes separately before writing any implementation.

Now mark the response no-cache. Does that mean it can never be stored? No: storage and reuse are different decisions, and successful validation is required for reuse under that directive. Change it to no-store. Can the lesson conclude that every prior copy was erased? No: the directive is not a retroactive deletion service. These questions are useful because they reveal whether the reader understands behavior rather than remembering two similar-sounding labels.

Finally, imagine a cached response for the wrong language. Increasing or decreasing max-age alone does not solve the matching problem; it changes how long a selected stored response may remain fresh. Investigate the representation selection and cache key. The transferable habit is to ask three questions in order: is this the right stored response, may it be reused now, and what evidence is needed if it cannot be reused directly? Those questions make cache behavior explainable without claiming that one header is a universal fix.

What this lesson leaves out

This introduction is not a production caching policy. It omits heuristic freshness, invalidation, partial responses and stale-while-revalidate. Measure real behavior before making speed claims.

A worked example you can check

Input

Simplified otherwise-cacheable response: max-age=60, initial age=0, ETag="v1".

Expected result

Age 59: fresh
Age 60: stale
Matching If-None-Match: 304, no new body
Changed validator: 200 with replacement body
What if it fails?

no-cache does not mean no storage. Real cache selection and age calculations include more rules than this fixture.

Original synthetic teaching fixture. No remote connection or real account is used.

References

Sources used to check the explanations and examples are listed below.

  1. HTTP freshness and cache directives
  2. HTTP validators and conditional requests

Found a mistake? Send a correction with this lesson’s title, URL and disputed detail. No login needed.

Continue learning

Read a URL before you share it →

DNS: finding an address without fetching a page →

All visual lessons and practical guides →