Volume 5

Q252: HTTP Caching ETags and Browser Cache Behavior

Difficulty: SeniorFrequency: HighAnswer time: 10-14 minutes

What Interviewers Want To Evaluate

Interviewers want to know whether you can explain caching beyond "the browser stores files."

They want to hear how freshness, validation, immutable assets, HTML, API data, CDNs, service workers, and user-specific responses fit together.

They also want to know whether you can avoid dangerous caching mistakes that leak data or show stale product state.

Short Interview Answer

HTTP caching lets browsers and shared caches reuse responses when cache headers say it is safe. Cache-Control defines freshness and storage rules, while ETag and Last-Modified allow validation with conditional requests. For frontend systems, I usually cache hashed static assets immutably, keep HTML and personalized data more conservative, use Vary carefully, and verify browser cache, CDN cache, and application cache separately when debugging stale content.

Detailed Interview Answer

Caching is one of the biggest frontend performance multipliers.

It is also one of the easiest ways to create confusing bugs.

The goal is not "cache everything."

The goal is to cache each response according to its risk and change pattern.

Freshness

Freshness answers one question:

Can this cached response be reused without asking the server again?

Cache-Control often defines this.

Common directives include:

max-age
s-maxage
public
private
no-cache
no-store
must-revalidate
immutable
stale-while-revalidate

max-age=31536000, immutable is excellent for hashed assets.

It is dangerous for unversioned HTML.

Validation

Validation means the browser has a cached response but asks the server whether it is still valid.

The server can respond:

304 Not Modified

That avoids downloading the full body again.

Validators include:

ETag
Last-Modified
If-None-Match
If-Modified-Since

An ETag is usually more precise than a timestamp.

It represents a version of the response.

Static Assets

Hashed assets are the safest caching target.

Example:

/assets/app.8f34c9.js
/assets/styles.91ab21.css
/images/hero.73aa.webp

When the content changes, the filename changes.

That allows:

Cache-Control: public, max-age=31536000, immutable

The browser can reuse the file confidently.

HTML Documents

HTML is usually more sensitive.

It points to the current asset graph.

If HTML is cached too aggressively, users can load old JavaScript bundles or miss new routes.

Common HTML strategies:

short max-age
no-cache with validation
CDN revalidation
ISR or static regeneration rules

In a Next.js app, generated pages, RSC payloads, and static assets can each have different caching behavior.

You need to inspect the actual headers.

API Responses

API caching depends on data type.

Public catalog data may be cacheable.

Personal dashboard data may not be safe for shared caches.

Mutation responses usually require careful invalidation.

Ask:

is this response public or private?
is it user-specific?
how stale can it be?
what invalidates it?
does it vary by auth, locale, device, or experiment?

If the answer includes user identity, avoid shared public caching unless the keying is absolutely correct.

The Vary Header

Vary tells caches which request headers affect the response.

Examples:

Vary: Accept-Encoding
Vary: Accept-Language
Vary: Cookie
Vary: Authorization

Vary can protect correctness.

It can also destroy cache efficiency if used broadly.

Vary: Cookie often makes shared caching difficult because many users have unique cookie values.

Browser Cache Versus CDN Cache

There are multiple caches:

memory cache
disk cache
HTTP browser cache
CDN edge cache
framework data cache
service worker cache
application state cache

A stale-content bug requires checking each layer.

Do not assume clearing React Query or SWR state fixes a CDN rule.

Do not assume purging a CDN fixes a service worker cache.

Debugging Stale Content

A strong debugging flow:

check the request URL
check status code
check from disk cache or memory cache
check Cache-Control
check Age
check ETag
check Vary
check CDN headers
check service worker involvement
check framework fetch cache mode
compare hard reload with normal reload

The Age header can reveal how long a response has lived in a shared cache.

The Network tab can reveal whether the browser even made a request.

Security Risks

Caching can leak sensitive data.

Avoid storing private user pages in shared caches.

Use conservative policies for:

profile data
billing data
tokens
medical or financial data
admin pages
permission-specific API results

Cache-Control: no-store is appropriate for highly sensitive responses.

private allows browser storage but prevents shared cache storage.

Interview Example

If asked, "How would you cache an ebook website?"

You can answer:

hashed JS/CSS/images: long immutable cache
public MDX pages: static generation or CDN cache with controlled revalidation
PDF exports: versioned URLs or validators
progress state: local browser storage, not shared server cache
authenticated pages: private or no-store depending on sensitivity

That shows you can separate content types.

Common Mistakes

Common mistakes include:

using no-store everywhere and losing performance
caching personalized data publicly
forgetting Vary for locale or auth differences
caching HTML forever
not versioning static assets
confusing no-cache with no-store
debugging stale UI without checking headers
forgetting service workers can serve old responses

Senior-Level Framing

Caching is a correctness system before it is a speed trick.

The senior framing:

"I classify responses by ownership, sensitivity, volatility, and invalidation path. Then I choose browser, CDN, framework, or application caching rules that preserve correctness while reducing unnecessary network and parsing work."

Practice Prompt

Pick three resources from a web app:

HTML page
JavaScript bundle
API response

For each, decide:

should it be cached?
who may cache it?
how long is it fresh?
how is it invalidated?
what headers prove that behavior?

Final Mental Model

Good caching makes the app feel instant.

Bad caching makes the app feel haunted by old state.

Treat every cache rule as a promise about freshness, privacy, and invalidation.