slew docs/runtimes/isr-caching

ISR and caching

Server responses can opt into platform caching with one standard header. slew then answers repeat requests from its own copy — instantly, even while your app is scaled to zero — and refreshes the copy in the background. This is incremental static regeneration (ISR) at the platform layer: visitors get static-file speed, your pages stay dynamic, and cold starts disappear from the request path.

Next.js needs no setup. A page with revalidate (or next: { revalidate: 60 } on a fetch) already emits exactly the header slew looks for. This matters more here than on always-on hosts: self-hosted Next keeps its ISR cache inside the instance, which scale-to-zero throws away — the platform copy is what survives.

Opting in

Send a Cache-Control with a shared-cache lifetime and stale-while-revalidate on any response:

Cache-Control: s-maxage=60, stale-while-revalidate=300

Any framework, any route — an Express handler, an Astro page, a SvelteKit +page.server.ts — the header is the whole contract. stale-while-revalidate without a value (Next's form) gets a 24-hour window.

What the platform does

Page age Behavior
Within s-maxage Served from the platform copy. Your app is not contacted — it can stay scaled to zero.
Within stale-while-revalidate The stale copy is served immediately; slew refetches from your app in the background and swaps the copy. A cold start happens inside that background refresh — the visitor never waits on it.
Beyond both The copy is dropped; the next request goes to your app normally.

If your app is down or crash-looping, stale copies keep answering until their window runs out — visitors see your last good page, not a 502.

Every deploy and rollback drops the project's copies: caching never delays a release. The response header X-Slew-Cache: HIT | STALE | MISS shows what happened to any request.

On-demand revalidation

Published in your CMS and don't want to wait out s-maxage? Evict specific pages from every platform cache layer — the CDN edge and the ISR copies — in one call:

curl -X POST https://api.slew.cloud/projects/<name>/revalidate \
  -H "Authorization: Bearer $SLEW_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"paths": ["/blog", "/blog/that-post"]}'
{ "ok": true, "hosts": ["myblog.slew.cloud", "www.myblog.com"], "paths": ["/blog", "/blog/that-post"] }
  • Up to 100 paths per call, each starting with /. Every hostname the project serves — subdomain, custom domains, branch domains — is purged.
  • Org deploy tokens may call it, so a CMS webhook can run on CI credentials instead of a personal token.
  • Calling revalidatePath() inside a Next app only clears Next's internal cache — the platform layers in front never see it. This endpoint is the platform half; call both when you self-manage revalidation.
  • The pages regenerate on their next request. Query-string variants of a purged path are dropped from the ISR copy; at the CDN edge they simply age out of their short TTL.

What is never cached

The platform copy is only ever a page anyone may see:

  • Only GET requests, only 200 responses.
  • no-store, no-cache, or private always win, and responses that set cookies or Vary on anything but encoding are skipped.
  • Requests carrying an Authorization header bypass the cache entirely.
  • On a password- or org-protected site, the access gate runs first — copies are only reachable by visitors who already unlocked the site.
  • Responses over 2 MB stream through uncached.