Next.js caching on your own server: ISR, the data cache and CDN headers

How Next.js caching behaves when self-hosted and what to configure so pages stay fresh.

Next.js caching works out of the box on Vercel because the platform wires it into its own infrastructure. On your own server, most of it still works, but a few assumptions change. Knowing them prevents stale pages and confusing deploys.

Where the cache lives

With next start or the standalone server, incremental static regeneration (ISR) and the data cache are stored on the local filesystem, inside .next/cache. In a container, that directory disappears on every deploy unless you mount it on a volume.

That is often fine: a fresh deploy starting with an empty cache simply regenerates pages on first request. It matters if regeneration is expensive or if you run several replicas.

Multiple replicas

Each replica keeps its own cache. One may serve a fresh page while another serves a stale one, and revalidatePath or revalidateTag called on one replica does not reach the others. Options:

  • Run a single replica, which is enough for many apps
  • Configure a shared cache handler, for example backed by Redis, using the cacheHandler option
  • Avoid ISR for pages that must be consistent and render them dynamically

Cache-Control headers

Next.js sets s-maxage and stale-while-revalidate headers for ISR pages. If you put a CDN in front, it will respect these. Without a CDN, browsers mostly ignore s-maxage, so the Node server handles every request, which is usually fine.

Static assets under /_next/static/ have hashed names and long cache headers. Serve them directly from the proxy or a CDN for a quick win.

On-demand revalidation

Webhooks from a CMS that call a revalidation route work the same as on Vercel, as long as the request reaches the replica that holds the cache. With a single replica, no extra work is needed.

Build time vs runtime

Pages rendered at build time contain data from the build moment. If the build runs in CI without access to production data, those pages may be empty or wrong. Either give the build access to the data it needs or make those pages dynamic.

Image optimization

next/image optimization works on self-hosted servers and caches results on disk. Install sharp in the production image for speed, and mount the cache if you want it to survive deploys.

Test before trusting

After deploying, change content in your CMS, trigger revalidation and confirm the page updates. Then restart the container and check again.

For the rest of the setup, from standalone output to HTTPS, see this guide to deploying Next.js to a VPS.

Disclosure: I work on Peon.


Write a comment