fetch results are cached across job runs — even with cache: 'no-store'
Describe the Bug
When running a recurring Payload job using TaskConfig, the same fetch() request seems to reuse cached results between job runs, even though cache: 'no-store' is explicitly passed to fetch.
This behavior causes scheduled jobs to keep processing the same response data every time instead of fetching a fresh response from the remote API.
Link to the code that reproduces this issue
https://github.com/cloud2303/payload-cache
Reproduction Steps
Example job definition:
export const RefreshWeChatToken: TaskConfig<'refreshWeChatToken'> = {
slug: 'refreshWeChatToken',
schedule: [
{
cron: '*/10 * * * * *',
queue: 'second',
},
],
retries: 0,
label: 'referesh token',
handler: async ({ req }) => {
// each time return different value
const url = 'http://127.0.0.1:4523/m2/6882259-6597789-default/362218398'
const response = await fetch(url, { cache: 'no-cache' })
const res = await response.json()
console.log(res)
return res
},
}
Logs output repeatedly every 10 seconds with identical data:
[14:49:30] INFO: Running 1 jobs.
new: 1
retrying: 0
{ access_token: 'adipisicing', expires_in: 79 }
[14:49:40] INFO: Running 1 jobs.
new: 1
retrying: 0
{ access_token: 'adipisicing', expires_in: 79 }
[14:49:50] INFO: Running 1 jobs.
new: 1
retrying: 0
{ access_token: 'adipisicing', expires_in: 79 }
[14:50:00] INFO: Running 1 jobs.
new: 1
retrying: 0
{ access_token: 'adipisicing', expires_in: 79 }
...
Even though the job reruns and fetch uses cache: 'no-store', the data returned never changes. This happens even when:
The mock server returns dynamic data when called externally.
The job handler is re-run by the internal Payload cron scheduler.
Which area(s) are affected? (Select all that apply)
Not sure
Environment Info
Binaries:
Node: 24.10.0
npm: N/A
Yarn: N/A
pnpm: N/A
Relevant Packages:
payload: 3.60.0
next: 15.4.4
@payloadcms/db-sqlite: 3.60.0
@payloadcms/drizzle: 3.60.0
@payloadcms/email-nodemailer: 3.60.0
@payloadcms/graphql: 3.60.0
@payloadcms/next/utilities: 3.60.0
@payloadcms/payload-cloud: 3.60.0
@payloadcms/richtext-lexical: 3.60.0
@payloadcms/translations: 3.60.0
@payloadcms/ui/shared: 3.60.0
react: 19.1.0
react-dom: 19.1.0
Operating System:
Platform: win32
Arch: x64
Version: Windows 11 Enterprise
Available memory (MB): 16099
Available CPU cores: 12
Also having this problem. Running 3.64.0.
I believe it's running in Nodejs, and it's not using Nextjs' fetch function, so make sure to add a timestamp, like
const cacheBuster = Date.now()
const url = `https://api.example.com/?_t=${cacheBuster}
I believe it's running in Nodejs, and it's not using Nextjs' fetch function, so make sure to add a timestamp, like
Thanks for the workaround. Let's look further for the root cause here. Because it should not cache, especially not with 'no-store' set.
Next.js extends the fetch() function with { cache: 'force-cache' | 'no-store' }, but the default fetch() function doesn't have it. So if cron jobs are running as Node.js process as a separate instance outside of Next.js context, it'd make sense. Maybe there's a way to bring the extended Next.js fetch() function.