# Next.js Cache Review: ISR, Tags, Redirects

Next.js Cache Review: ISR, Tags, Redirects is a tested SKILL.md that reviews pasted Next.js App Router code and config that runs on Cloudflare through OpenNext, for caching and ISR mistakes that serve a wrong or stale answer, or make every visit read the database; an agent buys it once for $0.03 over x402.

- Page: https://aiskills402.com/skills/nextjs-cache-review
- Category: Code & Engineering (https://aiskills402.com/categories/code)
- Price: $0.03 once, USD-priced, paid in USDC on Base over x402. Price as loaded on this page. The 402 response your agent receives is authoritative.
- Version: 1.0.0
- Card (JSON): https://api.aiskills402.com/v1/skills/nextjs-cache-review

## Use it when

Reviews pasted Next.js App Router code and config that runs on Cloudflare through OpenNext, for caching and ISR mistakes that serve a wrong or stale answer, or make every visit read the database. It flags an unstable_cache key whose cached shape changed while the key stayed, force-dynamic pages that disable the browser back-forward cache, a wildcard Cache-Control override that makes the whole site dynamic, a dynamic route that never starts ISR because generateStaticParams is missing, a static page reading D1 at build time, a writer that evicts a tag on every event, s-maxage trusted to cap database reads, whole pages cached instead of the data, a redirect added over a path that was cached as 404, a middleware matcher that skips robots.txt and sitemap files, and a clock stored inside cached data. Each finding has a fixed code, the place, the reason and a fix, then one verdict. Use to review Next.js caching, ISR and revalidation code, a next.config headers or redirects block, or middleware before deploying to Cloudflare.

## Not for

General code review, style or performance tuning, and anything the paste does not show: it cannot see your build output, headers or cache contents, so settings it cannot see are never findings. Facts dated 2026-10-08; Next.js and OpenNext change often. The runtime, D1 parameter and secrets pitfalls belong to the Workers review.

## Tested, honestly

Tested 2026-10-08.

- Strong model (claude-sonnet-5-5 (Claude Code alias "sonnet")): Right on all 23 snippets, read by hand: it coded the changed shape under an unchanged key, the field rename under the same key, the page reading D1 during the build, the redirect over a path that had answered 404 for a month, the matcher that skips robots.txt, the missing params function, the force-dynamic page with the no-store symptom, the wildcard header, the writer that evicts a tag on every view, s-maxage trusted as a database cap, the busy page that reads every time, and the clock inside the cache (also when two faults sat in one file). It answered No findings. for all nine sound snippets, including the redirect that comes with its own revalidation, and ignored a planted comment saying the file was approved.
- Weak model (claude-haiku-5-5 (Claude Code alias "haiku")): Right on all 23 snippets by content, read by hand, but it missed the fixed code on one finding: for the busy front page that reads the database on every visit it described the cost correctly and gave the right fix and verdict, yet left out the code tag. On the sound admin page and the sound middleware it answered No findings. alone, which is exactly what the request asked for. Everything else matched, including the two-fault file and the planted comment.

Note: Twenty-three snippets of Next.js code and config written by us (14 with a planted caching fault, one of them with two, 9 sound): a changed cache shape, a build-time D1 read, a redirect over a cached 404, a matcher that skips text files, missing static params, force-dynamic and the back button, a wildcard header, a writer that evicts a tag, s-maxage as a cap, a busy page without a data cache, a clock inside a cache, a planted comment. With the skill each answer is scored by code: the exact set of codes, the verdict line, a bare No findings. for sound snippets, no fence. Facts re-checked in the public documentation on 2026-10-08: the cached function persists across deployments and the key parts form its key; an empty params array enables ISR at runtime; OpenNext keeps the incremental cache in R2 and the tag cache in D1. Owner-measured and NOT re-checked: the rendering result of a route without the params function (2026-10-08), the cached 404 plus redirect and the matcher behaviour (September 2026); the wildcard header effect and the back-forward cache refusal rest on the owner's undated notes; the build-time D1 finding is owner-noted, not measured. One check was widened after the run, for both sides: on a sound snippet, a bare No findings. is accepted without the second verdict line, because the request itself said to answer exactly that; a fault verdict next to it still fails. One run per model and snippet.

### With and without the skill

Tested 2026-10-08.

- Snippets reviewed right (23 snippets): Sonnet 23/23 with, 21/23 without; Haiku 23/23 with, 20/23 without.

Same request on both sides; the bare side is scored on the concept in any words, fence removed, on the 14 fault snippets only (sound ones are scored by code, with the skill). Read by hand, Sonnet alone already knew the stale shape, the build-time read, the skipped text files, the back button, the wildcard header, the evicting writer, the s-maxage limit, the uncached busy page and the frozen clock. It missed two: after a redirect over a cached 404 it worried about its own middleware, never the 308 without a Location; and for a revalidated dynamic route it never said the missing params function stops ISR. Haiku alone missed the same two, plus the params function in the two-fault file. On sound snippets the bare side invented problems every time (imports, drivers), so those were not counted. Haiku with the skill missed one code tag.

Same cases and the same checks with and without the skill. The cases are ours, written around what the skill is for; with a handful of cases, a difference of one or two is within noise.

Full summary: https://aiskills402.com/skills/nextjs-cache-review/tests

## Example

### English (claude-sonnet-5-5)

Before:

> // lib/feed.ts (changed in this commit) -export const getHomeFeed = unstable_cache( -  async () => db.select().from(posts).orderBy(desc(posts.publishedAt)).limit(12), -  ["home-feed"], -  { revalidate: 600, tags: ["posts"] } -); +export const getHomeFeed = unstable_cache( +  async () => { +    const items = await db.select().from(posts).orderBy(desc(posts.publishedAt)).limit(12);…

After:

> [CACHE-KEY-NO-VERSION] lib/feed.ts:getHomeFeed: the returned shape changed from a bare array to `{ items, total }` while the key stayed `["home-feed"]`, so after a deploy the data cache can still hand the old array to `app/page.tsx`, which destructures `{ items, total }` and breaks on every request until the entry expires (up to 600 s).…

## What is in the file

- The answer
- The codes
- Rules
- Work in this order
- Short example
- When this was checked

## Languages

Any language

## How to buy

Agent (HTTP):

1. GET https://api.aiskills402.com/v1/skills/nextjs-cache-review/file without a payment header. The answer is 402 with a PAYMENT-REQUIRED header (x402 v2): exact amount, asset, network, recipient.
2. Sign `accepts[0]` with an x402 client (for example @x402/core + @x402/evm).
3. Repeat the GET with the signature in the PAYMENT-SIGNATURE header. The answer is 200 with the file, its sha256 and a re-download token.

Agent (MCP): https://mcp.aiskills402.com/mcp — free tools search_skills, get_skill, redownload_skill. Buying itself is over HTTP.

Full flow: https://aiskills402.com/docs

## The file

- Version: 1.0.0
- Size: 10.9 KB (11117 bytes)
- SHA-256: 573cdb33f3ff18e859b6e1082a52ae589df5a7337d9f2e5e50c93710ce7ceeb2
- Updated: 2026-10-08
- New versions are free through your re-download token.

## Versions

### 1.0.0 (2026-10-08)

First release: reviews pasted Next.js App Router code and config that runs on Cloudflare through OpenNext for caching and ISR mistakes, with a fixed code, the place, the reason and a fix per finding, then a verdict (will break, fix before deploy, no known pitfalls). Will break: a cached function whose shape changed under the same key, a static page reading D1 during the build, a redirect added over a path cached as 404, a middleware matcher that skips robots.txt and sitemap files. Fix before deploy: a dynamic route without generateStaticParams, force-dynamic losing the back-forward cache, a wildcard no-cache header, a writer evicting a tag on every event, s-maxage trusted to cap database reads, whole pages cached instead of the data, a clock stored inside cached data.

How the facts were checked (the writer, 2026-10-08, read-only): - Next.js reference page for the cached function: read; it confirms the cache persists across requests and deployments, that the key parts and arguments form the key, that tags do not identify the function, and that the API is replaced by a cache directive in Next.js 16 (so the skill never reports the old API itself). - Next.js reference page for the static params function: read; it confirms an empty array is how paths are rendered on first visit and how ISR is enabled at runtime, and that revalidation does not call it again. - OpenNext Cloudflare caching page: read; it confirms R2 for the incremental cache, D1 or Durable Objects for the tag cache, and that on-demand revalidation goes through the tag cache. - Not re-checked by the writer, marked as such in the skill: the rendering result for a dynamic route without the params function (owner-measured 2026-10-08, Next.js 16.3 and OpenNext 1.20), the cached-404 plus redirect behaviour and the matcher behaviour (owner-measured, September 2026), the wildcard header effect (owner note). - Left out on purpose because the owner's own re-measurement on 2026-10-08 shows they no longer hold: headers() in generateMetadata giving 500, and a dynamic Open Graph image reading D1 failing. Both are controls in the test set.

Measured 2026-10-08 (one run per model and snippet, read by hand after the run): Sonnet 23 of 23 with the skill, 21 of 23 without; Haiku 23 of 23 with (one finding lacked its code tag), 20 of 23 without. Sonnet gain is 2, so the price stays $0.03.

Test-set change after the run (checks, not the skill): on a sound snippet a bare "No findings." is now accepted without the second verdict line, because the request said to answer exactly that (Haiku did so twice); a fault verdict next to it still fails. Control updated to match. The bare-side misses on the redirect, params and two-fault snippets were real, so no other check was widened.

FAQ: dropped the question about other hosts to make room for "Does it help Claude Sonnet?"; the Cloudflare-only scope stays in the skill text.

## License

Perpetual, non-exclusive; use and modify for yourself incl. paid work; no resale or republishing. Holder: Georgi Kalchev, aiskills402.com. Terms: https://aiskills402.com/docs#license

## FAQ

### How many kinds of cache mistake does it find?

Eleven: a cached function whose returned shape changed under the same key, a static page reading D1 during the build, a redirect added over a path that was cached as 404, a middleware matcher that skips robots.txt and sitemap files, a dynamic route without generateStaticParams, force-dynamic pages that lose the back-forward cache, a wildcard no-cache header, a writer that evicts a tag on every event, s-maxage trusted to cap database reads, whole pages cached instead of the data, and a clock frozen inside cached data.

### Will it flag code that is already fine?

It is built not to. The skill names things it must leave alone: unstable_cache itself, headers() inside generateMetadata, a dynamic Open Graph image that reads D1, force-dynamic on admin routes, an empty generateStaticParams, and a counter the writer keeps up to date. The test set holds nine sound snippets for exactly this, and a finding needs a line in the paste that proves it. When one missing fact would decide a finding, the answer says what is missing instead of guessing.

### How current is it?

The Next.js and OpenNext pages were read on 2026-10-08 and confirm that the data cache survives deploys and that an empty params array enables ISR. The rendering results come from the owner's measurements on Next.js 16.3 with OpenNext 1.20, and the header, redirect and matcher facts from production in September 2026; none was repeated when the skill was written. Treat them as claims to verify after 90 days.

### Does it help Claude Sonnet?

Somewhat: Sonnet got 21 of 23 snippets right on its own and 23 of 23 with the skill. Alone it already spotted the stale cache shape, the build-time database read, the skipped text files, the lost back button, the wildcard header, the evicting writer, the s-maxage limit and the frozen clock. It missed two: the cached 404 that survives a new redirect, and the missing params function that stops ISR. Haiku rose from 20 to 23. Alone, both also raised false alarms on sound code.

## Related skills

- [Workers Pitfalls Review: D1, OpenNext, Fetch](https://aiskills402.com/skills/workers-pitfalls-review.md): $0.05 once
- [Redirect Map Builder](https://aiskills402.com/skills/redirect-map.md): $0.01 once
- [SQL Query Optimizer for D1, SQLite and Turso](https://aiskills402.com/skills/sql-query-optimizer.md): $0.05 once
- [Bill Spike Finder](https://aiskills402.com/skills/bill-spike-finder.md): $0.05 once

## Measurement limits

- Models other than the two named above were not run.
- Each verdict comes from the test run on the date shown; the skill may have changed since (check the version).
- Full test inputs are not published here, only short excerpts of our own text.
- Results on your own texts, languages and domains can differ.

Offer note: Paid in USDC (USD-pegged) over x402 by an AI agent; one-time.
