Skip to content

fix: 304 not modified reply upon revalidation did not update cache.#4617

Merged
mcollina merged 5 commits intonodejs:mainfrom
daan944:fix-304-revalidation
Oct 11, 2025
Merged

fix: 304 not modified reply upon revalidation did not update cache.#4617
mcollina merged 5 commits intonodejs:mainfrom
daan944:fix-304-revalidation

Conversation

@daan944
Copy link
Contributor

@daan944 daan944 commented Oct 8, 2025

This relates to...

#4596

Rationale

When a 304 was returned during revalidation, the cache was not updated to reflect this. Instead, the cached value was kept as-is, eventually expiring. This is particularly a problem for anyone using stale-while-revalidate, as in the entire stale-while-revalidate window there'll be no updates while loading the backend with (async) revalidations.

To handle a 304, the cached body and headers will be re-used and re-inserted into cache. This is not the most optimal way, but the only way I feel is possible without breaking changes. A better way would be to require support for an update method in the cacheStore to only update the headers/metadata and keep body as-is. I didn't want to go there without discussing it first.

Changes

  1. 304 not modified replies will update the cache with new headers, cache times etc., but will re-use original statuscode/message, etag and body. (see changes in lib/handler/cache-handler.js)
  2. Manual re-validation possible by performing a request with if-modified-since or if-none-match. These will trigger a synchronous revalidation flow.
  3. Removed two tests (stale responses are revalidated before deleteAt (if-modified-since) and stale responses are revalidated before deleteAt (if-none-match) from test/interceptors/cache.js as these did not contain the actual expected behavior. Instead I've added revalidates the request, handles 304s during stale-while-revalidate in test/interceptors/cache-revalidate-stale.js.

Bug Fixes

See #4596

Breaking Changes and Deprecations

None

Status

@codecov-commenter
Copy link

codecov-commenter commented Oct 9, 2025

Codecov Report

❌ Patch coverage is 84.54545% with 17 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.93%. Comparing base (6d912de) to head (23a7c38).

Files with missing lines Patch % Lines
lib/handler/cache-handler.js 82.14% 15 Missing ⚠️
lib/interceptor/cache.js 92.30% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4617      +/-   ##
==========================================
- Coverage   92.95%   92.93%   -0.02%     
==========================================
  Files         106      106              
  Lines       33015    33091      +76     
==========================================
+ Hits        30688    30753      +65     
- Misses       2327     2338      +11     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

}
})

test('stale responses are revalidated before deleteAt (if-modified-since)', async () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this deleted?

Copy link
Contributor Author

@daan944 daan944 Oct 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel this is covered by the other tests already (incl the ones I've added).

Also, on line 491 and 627 there's conditional requests that behave different now: they update the cache too. The scenario in these tests are thus now not entirely valid anymore.

If you prefer I could modify and reinstate them.

I do feel the organisation of the cache/revalidation tests can be improved, as we have both these tests and the ones in test/interceptors/cache-revalidate-stale.js - shouldn't we merge these files?

@mcollina
Copy link
Member

mcollina commented Oct 9, 2025

@metcoder95 ptal

@mcollina mcollina merged commit cac98ab into nodejs:main Oct 11, 2025
27 of 29 checks passed
@daan944 daan944 deleted the fix-304-revalidation branch October 13, 2025 08:30
@github-actions github-actions bot mentioned this pull request Jan 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants