Upgrading to Astro 7: the Rust compiler is fast, the cold cache is what bit me
Astro 7 moved the compiler and the Markdown pipeline to Rust and switched the bundler to Rolldown. The upgrade was quick; the failures it surfaced afterwards were not.
Astro 7 shipped on 22 June 2026, and the pitch is one sentence long: this release is all about speed.
Quite a lot changed underneath:
- The
.astrocompiler was rewritten in Rust - Markdown and MDX now run through a new Rust-powered pipeline
- The rendering engine was replaced with a queue-based approach
- Vite 8, and with it the Rolldown bundler
- 15–61% faster builds in Astro’s own benchmarks
- Route caching stabilised, plus experimental CDN cache providers for Netlify, Vercel and Cloudflare
- Advanced Routing: a
src/fetch.tsentrypoint that can take over the request pipeline - Agent detection, a background dev server, and structured JSON logs for AI coding assistants
This site is 533 pages, 40 stylesheets and a 532-page search index. The upgrade itself was cheap. What cost me time was everything that surfaced after it.
Trap one: a CJS-only dependency stops being pre-bundled
The first astro sync after upgrading died with:
require is not defined
The cause was not my code. The content collection (src/content.config.ts, via the glob loader from astro/loaders) has a CJS-only package on its dependency chain, and content collections are evaluated in a Vite environment literally named astro — neither client nor ssr. A top-level optimizeDeps only feeds client, so that package was never pre-bundled in the astro environment, and the module runner evaluated a CJS file as ESM.
The fix is to name the environment explicitly:
optimizeDeps: { include: ['picomatch'] }, // the client environment
environments: { astro: { optimizeDeps: { include: ['picomatch'] } } }, // the astro environment
You need both. And only astro, never ssr — writing both makes astro dev return 500 for the entire site.
Trap two: a warm cache hides the real failure
I thought I had fixed the above earlier by deleting that workaround. Dev came back immediately and the build was green.
That was a false green. node_modules/.vite is in .gitignore, so it is always warm locally, and a warm cache still holds dependencies produced by the previous build. Delete the cache and the first step fails with exactly the same error.
The only valid way to conclude “this workaround can go” is to re-verify on a cold cache: remove
node_modules/.vite, or run it on a clean machine or in CI. Green locally proves nothing.
Trap three: a passing build does not mean dev runs
This project has two failure modes that look nothing alike:
astro buildis fine end to end, butastro devreturns 500 on every request with a single line about a missing component instance.- Dev prints “ready”, then returns 500 on every request.
So after touching build configuration, seeing “ready” is not enough — you have to actually request a page and check for a 200.
How I upgrade now
Four steps, always in this order:
- Delete
node_modules/.vite(and.astro), then runastro synccold npm run checkmust report 0 errors / 0 warnings / 0 hintsnpm run buildmust produce the expected page count- Start dev and request at least five different routes (home, a list, an article, an app, the language entry page) and confirm they all return 200
Step four is the one most likely to be skipped, and the one most likely to break. Every time I skipped it, I paid for it later.

Comments
…