Code & Engineering

Next.js Cache Review: ISR, Tags, Redirects

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.

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.

Tested 2026-10-08No code, no hidden instructionsv1.0.0 · 10.9 KB · perpetual license

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 with a strong and a weak model.

With and without the skill

Results with and without the skill, for Sonnet and Haiku
SonnetHaiku
withwithoutwithwithout
Snippets reviewed right (23 snippets)23/2321/2323/2320/23

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.

SonnetStrong model, claude-sonnet-5-5
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.
HaikuWeak model, claude-haiku-5-5
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.

Full test summary

Example

Our own test text, before and after the skill ran. Excerpts only.

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. Tried in: English.

License

Perpetual, non-exclusive; use and modify for yourself incl. paid work; no resale or republishing. Holder: Georgi Kalchev, aiskills402.com. Full terms.

Versions

Current version 1.0.0, updated 2026-10-08. Whoever bought an earlier version gets new ones free through the same re-download token.

  1. v1.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.

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.

Share

Read this page as Markdown: /skills/nextjs-cache-review.md.

  • Workers Pitfalls Review: D1, OpenNext, Fetch

    Code & Engineering

    SKILL.md · v1.2.0 · 9.8 KB

    Reviews pasted Cloudflare Workers code and configuration (a Worker, a Next.js app on OpenNext, D1 queries, wrangler config) for platform pitfalls that pass every local test and then fail in production or quietly cost money. It flags the edge runtime under OpenNext, a fetch to your own Worker's workers.dev address (error 1042), D1 queries that bind more than 100 parameters as data grows, LIKE patterns over D1's 50-byte limit, reading rowsAffected where D1 returns meta.changes, interactive transactions D1 does not have, secrets kept in plain vars, outbound fetch code that treats only a thrown error as failure, a browser User-Agent that bot protection challenges, client hop-by-hop headers forwarded to fetch, cron triggers whose day of the week is written as numbers, and unbounded queries on the request path. Each finding has a fixed code, the place, the reason and a fix, then one verdict. Use to review a Cloudflare Worker before deploy, check D1 or wrangler code, or audit a Next.js app running on Cloudflare.

    $0.05once

    • x402
    • USDC
    • Base
    Get skill

    Tested with Sonnet and Haiku, 8 Oct 2026

  • Redirect Map Builder

    SEO & Content

    SKILL.md · v1.0.0 · 8.8 KB

    Turns an old-URL list and the mappings you have into a redirect map as JSON - one rule per old URL, chains collapsed to the final target, loops reported and never emitted, queries and percent-encoding kept as written, and old URLs with no named target listed as unmapped instead of guessed. Also writes the same map as a Cloudflare Pages style _redirects file. Knows the status codes (301 for a moved page, 308 where the method must be kept and what Next.js really sends for permanent true) and the cache trap, where a redirect added over a cached 404 keeps serving a 308 with no Location until the path is purged. Use when asked to plan or write redirects for a site migration, a redesign, a URL rename or a domain change, or to check a redirect list for chains and loops.

    $0.01once

    • x402
    • USDC
    • Base
    Get skill

    Tested with Sonnet and Haiku, 8 Oct 2026

  • SQL Query Optimizer for D1, SQLite and Turso

    Code & Engineering

    SKILL.md · v1.0.2 · 9.8 KB

    Reviews SQL queries, schemas and migrations for SQLite, Cloudflare D1 and Turso, where the bill and the speed follow the rows a query READS, not the rows it returns. Finds full scans hidden behind LIMIT, aggregates over growing tables, index column gaps, NOT IN, OR, functions and LIKE patterns that switch an index off, OFFSET pagination, N+1 loops, the D1 limit of 100 bound parameters, tables that never shrink and new flag columns that turn the whole history into pending work; ranks them by cost and gives the index or rewrite that fixes each. Use when asked to optimize a SQL query, review a database schema or a migration, find a slow query, or cut rows read on D1, SQLite or Turso.

    $0.05once

    • x402
    • USDC
    • Base
    Get skill

    Tested with Sonnet and Haiku, 3 Oct 2026

  • Bill Spike Finder

    Code & Engineering

    SKILL.md · v1.0.0 · 15.9 KB

    Finds the loops behind a bill spike or an unexpected bill. Reviews a web app's code and config for loops and repeats that run up the bill on their own on Vercel, Turso, Cloudflare Workers and D1 and paid AI APIs. Finds two schedulers on one job, retries without a cap, work that triggers itself, client polling and React render loops, caches cleared on every write, middleware running on every static file, queues that resend failures forever, image settings that multiply transformations, health checks that count whole tables, alerts sent on every run and bots crawling endless filter URLs. Counts the runs per month, names the billed unit, ranks by cost and gives the change that stops each one. Use when asked why a Vercel, Turso or Cloudflare bill jumped, to find an infinite loop or a runaway cost, or to review a cron job, webhook, queue consumer, middleware or polling code before it ships.

    $0.05once

    • x402
    • USDC
    • Base
    Get skill

    Tested with Sonnet and Haiku, 4 Oct 2026