AI & Agent Dev Bug Sandbox logo
AI & Agent Dev Bug Sandbox
Back to Radar

On-Demand ISR Revalidation Reports Success But Serves Stale Content When A Background Render Is In-Flight

In Next.js Pages Router, calling res.revalidate('/') after a content publish can return success while the next request still serves the pre-publish version. This occurs when a normal background ISR render is already in-flight and reads data before publication; the on-demand revalidation reuses that in-flight render, and the stale result is persisted with a fresh cache timestamp.

highConfidence 87%Next.jsAffected V16.3.6Affected V16.4.0-Canary.48Affected V16.4.0-Canary.50

Origin Analysis

ResponseCache separates normal and on-demand requests in its get batcher, but the later revalidateBatcher keys only on the route key. An on-demand revalidation can therefore join an existing normal render that read data before publication, and that older result is then stored as if it were fresh. Regression follows #80853.
1. Create a Pages Router page with getStaticProps that reads a version and adds a 3-second render delay.\n2. Build and start the app.\n3. Request the page to get a STALE response and trigger a background render reading version N.\n4. After 0.75 seconds, publish version N+1 and call res.revalidate('/').\n5. Wait 1 second and request the page again.\n6. Observe that x-nextjs-cache is HIT and the served version is still N, while the API reported revalidated:true.

Fixing Code Block

Edge Case Audit

The in-memory token map is process-local; in multi-instance or serverless deployments sharing a cache handler, a stale render from another instance may still overwrite after an on-demand revalidation on a different instance. Tokens also accumulate indefinitely without cleanup; add a TTL or remove entries after cache set completes. Rollback: revert to next@15.5.10 or disable on-demand revalidation until an official fix is available. Test with existing normal ISR intervals to ensure no cache poisoning.

Ecosystem Topology