Skip to content

feat: staleTime and stale-while-revalidate - #26

Merged
nigrosimone merged 1 commit into
mainfrom
feat/stale-while-revalidate
Sep 2, 2026
Merged

nigrosimone merged 1 commit into
mainfrom
feat/stale-while-revalidate

Conversation

@nigrosimone

Copy link
Copy Markdown
Owner

Until now an entry was either fresh, and served, or expired, and refetched with the caller waiting for it. So the first request after the expiration always paid a full round trip, even if the body was in the cache a millisecond before.

staleTime adds a freshness window inside lifetime. Past it the cached response is still served right away, and the entry is refreshed in background for the next reader. The subscriber still gets one response, so firstValueFrom keeps working; a failed refresh keeps the old entry and is not thrown at the caller; parallel hits send a single refresh. It is off by default (staleTime: undefined), nothing changes for who does not set it.

The entry now also carries freshTime, the moment the body came from the backend, so slidingExpiration keeps an entry into the cache without making it fresh again. Entries stored by an older version fall back to addedTime. There is a new isStale(entry, req) hook, overridable per request like the others, and nothing is ever stale while rendering on the server.

The cache is now read before the queue: while a stale entry is being refreshed its key is in the queue, and joining that request would make the caller wait for the network instead of serving the response we already have.

Eleven tests, each one checked that it fails without the change.

@nigrosimone
nigrosimone merged commit be448bd into main Sep 2, 2026
3 checks passed
@nigrosimone
nigrosimone deleted the feat/stale-while-revalidate branch September 2, 2026 05:43
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.

1 participant