You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Add max_stale parameter to refresh_mode="background" for configurable stale grace window #17009
I have searched the existing issues for similar feature requests.
I added a descriptive title and summary to this issue.
Summary
When using refresh_mode="background" on st.cache_data / st.cache_resource, the stale grace window is fixed at 1×TTL (hard expiry at 2×TTL). This means an app idle overnight (longer than 2×TTL) has its cache evicted and the first morning user blocks on a cold miss.
A max_stale parameter would let users configure the stale grace window independently from TTL:
This separates two concerns: how often to refresh (ttl="2m") from how long stale data is acceptable (max_stale="12h"). Users who want frequent freshness checks but never want to block get exactly that.
Is there any way that we can influence the "2 × ttl" background cache timeout? In my use case I want a short ttl so the values are updated often, but I never want my users to have to wait for a response. I would like to set the ttl to something like 2 minutes, but the oldest background cache that's allowed to be served can be much older than four minutes.
This is also the more practical solution for the "first user of the day" problem compared to cron scheduling, since it does not require an always-on server and works on scale-to-zero deployments.
max_stale parameter: Explicitly configure the stale grace window (default: equal to ttl), e.g. ttl="1h", max_stale="12h" to serve stale data across an overnight idle gap without blocking the first morning user
This is an enhancement request to add a per-function max_stale parameter on st.cache_data / st.cache_resource so refresh_mode="background" can keep serving stale data longer than the current 1 × ttl grace window (hard expiry at 2 × ttl by default). The goal is to refresh often (ttl="2m") without blocking the first user after an overnight idle gap (max_stale="12h"), especially on scale-to-zero hosts where cron/pre-warm is impractical.
This is already documented as future work in the background refresh product spec. Today the bound is process-wide only: runner.cacheBackgroundRefreshTTLMultiplier (default 2.0, shipped in #16599). Raising that option can cover a single long-idle cache, but it also lengthens the stale window for every other background cache in the process.
Related Issues
#11050 — Origin of this request. Background refresh and lifespan cache warming landed there; @itsToggle then asked to decouple the 2 × ttl hard bound from the freshness TTL.
#8645 — Original stale-while-revalidate cache refresh request, implemented as refresh_mode="background". This issue extends that design with a per-function stale limit.
#6687 — Open request for background/cron-style execution. A scheduled refresher is an always-on alternative to max_stale for the “first user of the day” problem.
This is an automated triage comment using cursor-grok-4.6-xhigh. Please verify the suggested labels and related issues.
Activity
github-actions commentedon Sep 17, 2026
To help Streamlit prioritize this feature, react with a 👍 (thumbs up emoji) to the initial post.
Your vote helps us identify which enhancements matter most to our users.
lukasmasuch commentedon Sep 17, 2026
Related aspect: you can configure the stale period via
runner.cacheBackgroundRefreshTTLMultiplieracross the entire app, but not per cache function.github-actions commentedon Sep 17, 2026
This is an enhancement request to add a per-function
max_staleparameter onst.cache_data/st.cache_resourcesorefresh_mode="background"can keep serving stale data longer than the current1 × ttlgrace window (hard expiry at2 × ttlby default). The goal is to refresh often (ttl="2m") without blocking the first user after an overnight idle gap (max_stale="12h"), especially on scale-to-zero hosts where cron/pre-warm is impractical.This is already documented as future work in the background refresh product spec. Today the bound is process-wide only:
runner.cacheBackgroundRefreshTTLMultiplier(default2.0, shipped in #16599). Raising that option can cover a single long-idle cache, but it also lengthens the stale window for every other background cache in the process.Related Issues
2 × ttlhard bound from the freshness TTL.refresh_mode="background". This issue extends that design with a per-function stale limit.max_stalefor the “first user of the day” problem.This is an automated triage comment using
cursor-grok-4.6-xhigh. Please verify the suggested labels and related issues.