Astro SSR Cache Growth During Dev: Is Cache Invalidation Handled?
0 reputation · 13 Jun 2025, 17:53 UTC
0 reputation · 13 Jun 2025, 17:53 UTC
When running astro dev, repeated page reloads in the browser appear to increase the Node process heap over time. The suspected culprit is Astro’s SSR cache, which keeps component instances alive across requests to speed up rendering.
The dev workflow uses Vite’s hot‑module‑replacement and a Vite in‑memory file cache. Dynamic imports of large libraries are cached by Vite as well. Node.js 20’s garbage collector behaves differently from older LTS releases, and the HMR cycle may mask leaks that only appear in production builds.
The unresolved decision is whether Astro intentionally keeps its SSR cache alive between dev requests, and how cache invalidation is supposed to work. The questions are: 1) Does Astro expose a flag or API to clear the SSR cache on each request? 2) Is Vite’s file cache fully cleared when files are deleted or renamed during watch mode? 3) Should developers manually purge integration caches to avoid memory bloat?
29775 reputation · 14 Jun 2025, 00:48 UTC
There is no Astro flag or API to "clear the SSR cache per request," because the growth you're seeing almost certainly isn't an Astro SSR cache at all. In astro dev, Astro renders each request fresh; the memory that accumulates lives in Vite's in-memory module graph, which HMR intentionally keeps alive. That is expected behavior, not a leak — though it can hide real leaks, so verification matters.
Confirmed: Astro's dev server runs on Vite. Vite maintains a module graph in memory so that when a file changes, only the affected modules are invalidated and re-transformed. Invalidated modules are dropped from the graph, but Vite does not purge the process heap — the old module closures, source maps, and transform results become garbage that Node's collector reclaims on its own schedule.
Likely, but verify: The steady heap climb across reloads is the module graph plus Vite's transform cache growing as you edit files, combined with Node 20's GC being less aggressive about returning memory to the OS. Large dynamic imports add to the baseline because Vite caches their transformed output. None of this implies component instances are pinned across requests — Astro's rendering pipeline is stateless per request outside the Vite layer.
node_modules/.vite is a separate concern; it is content-hashed and safe to delete manually (rm -rf node_modules/.vite) if you suspect staleness. Whether every rename edge case fully invalidates in your specific Vite version is worth verifying against the Vite changelog — treat this as version-dependent.Start the dev server with inspection enabled:
node --inspect ./node_modules/.bin/astro devIn Chrome DevTools' Memory tab, take a heap snapshot, reload the page 20–30 times, force garbage collection, and take another. If retained size plateaus after GC, you're looking at normal cache behavior. If it climbs monotonically, compare dominators between snapshots to find the retainer. As a control, run a production build (astro build then node ./dist/server/entry.mjs) under the same load — production has no Vite module graph, so growth there indicates a genuine application-level leak.
One detail that would change this advice: does the heap keep growing if you reload without editing any files? If yes, profile before assuming it's Vite — that pattern points away from HMR invalidation and toward something in your own request path.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.