Synchronize Stale time #10726
Replies: 5 comments
-
|
Instead of a countdown, use clock alignment, make all queries expire at the same fixed points in time, TanStack v5 lets staleTime accept a function that returns a number. You calculate "how many milliseconds until the next 5-minute mark" and return that. Every query, no matter when it loads, will go stale at the same clock boundary. Apply the same function to all related queries and they'll always expire together. |
Beta Was this translation helpful? Give feedback.
-
|
The simplest fix is to structure your keys with a shared prefix and invalidate them together. useQuery({ queryKey: ['invoices', 'summary'], queryFn: fetchSummary })
useQuery({ queryKey: ['invoices', 'list'], queryFn: fetchInvoices })
useQuery({ queryKey: ['invoices', 'detail', id], queryFn: () => fetchInvoice(id) })Then after any mutation that touches invoice data: queryClient.invalidateQueries({ queryKey: ['invoices'] })This forces every query under the If you're polling instead of doing mutation-based invalidation, set the same |
Beta Was this translation helpful? Give feedback.
-
|
The issue is that Solution — Use a TanStack Query v5 lets const INTERVAL = 5 * 60 * 1000; // 5 minutes
const alignedStaleTime = () => {
const now = Date.now();
const nextTick = Math.ceil(now / INTERVAL) * INTERVAL;
return nextTick - now;
};
// Use the same function for all related queries
useQuery({
queryKey: ['invoice-summary'],
queryFn: fetchInvoiceSummary,
staleTime: alignedStaleTime,
});
useQuery({
queryKey: ['invoices'],
queryFn: fetchInvoices,
staleTime: alignedStaleTime,
});This way, all queries become stale at the same wall-clock moment, regardless of when they were individually fetched. They'll all refetch together on the next window focus or interval. Alternative — Use a shared // Invalidate all invoice-related queries at once
queryClient.invalidateQueries({ queryKey: ['invoice'] });This forces all queries with a matching prefix to refetch simultaneously, which guarantees they show consistent data. |
Beta Was this translation helpful? Give feedback.
-
|
Thanks for the advice going to try the function for stale time.
…On Mon, 25 May 2026, 15:09 Aymen Hmaidi, ***@***.***> wrote:
The issue is that staleTime starts counting from when each query's data
was last fetched. If queries fire at different times, they'll naturally
drift apart.
*Solution — Use a staleTime function to align all queries to the same
clock:*
TanStack Query v5 lets staleTime accept a function. You can align all
queries to expire at the same fixed intervals (e.g., every 5 minutes on the
clock):
const INTERVAL = 5 * 60 * 1000; // 5 minutes
const alignedStaleTime = () => {
const now = Date.now();
const nextTick = Math.ceil(now / INTERVAL) * INTERVAL;
return nextTick - now;};
// Use the same function for all related queriesuseQuery({
queryKey: ['invoice-summary'],
queryFn: fetchInvoiceSummary,
staleTime: alignedStaleTime,});
useQuery({
queryKey: ['invoices'],
queryFn: fetchInvoices,
staleTime: alignedStaleTime,});
This way, all queries become stale at the same wall-clock moment,
regardless of when they were individually fetched. They'll all refetch
together on the next window focus or interval.
*Alternative — Use a shared queryKey prefix and invalidate together:*
// Invalidate all invoice-related queries at oncequeryClient.invalidateQueries({ queryKey: ['invoice'] });
This forces all queries with a matching prefix to refetch simultaneously,
which guarantees they show consistent data.
—
Reply to this email directly, view it on GitHub
<#10726 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AACOS7X5UIOHTB4LNOB5HF344RHYPAVCNFSM6AAAAACZC5UKXSVHI2DSMVQWIX3LMV43URDJONRXK43TNFXW4Q3PNVWWK3TUHMYTOMBVGA4TONQ>
.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
|
The core issue here is that each query's There are a few approaches to solve this depending on what "synchronized" means to you. Option 1: Aligned
|
| Goal | Best approach |
|---|---|
| Stale at the same wall-clock time | Option 1: alignedStaleTime function |
| Active refresh at the same moment | Option 2: Scheduled invalidateQueries |
| Manual coordinated refresh trigger | Option 3: Shared prefix + invalidateQueries |
Option 1 is the most elegant for your use case — it's purely declarative, requires no side effects or timers, and ensures all queries become stale at the same fixed interval boundaries no matter when they were last fetched.
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
I have a number of api endpoints that show data but could be viewed from various screens and the stale time whilst set to the same value will be based on when they open the screen eg
/api/invoice-summary
/api/invoices
/api/inoivce/1/
The issue i have is the stale time will expire differently dependng when the queries are triggered which means they can get out of synch, where i would prefer there are synced so that i have some confiendence they are showing similar values. is that possible?
thanks
Beta Was this translation helpful? Give feedback.
All reactions