Back to writing
Javascript · Rust · Website

Astro 7 is here, and it's all about build speed

/ 2 min read

Astro 7 rewrote the compiler in Rust, moved Markdown to a Rust pipeline, and shipped Vite 8. Builds are 15 to 61 percent faster. Here's what to upgrade now.

Astro 7 release: faster builds with a Rust compiler and Vite 8
On this page

I run Astro on client sites, and the thing I watch on a big build is the clock. A docs site with thousands of pages can sit there for two or three minutes every deploy. So when the Astro team says version 7 is "all about speed," I read the benchmarks before I get excited.

Astro 7 shipped on 22 June 2026. The short version: most of the slow parts of a build got rewritten in Rust, and the whole thing rides on Vite 8 with a new bundler. The team's own numbers show builds 15 to 61 percent faster, and a few sites more than twice as fast. This is the same move TypeScript made when it rewrote its compiler in Go: when a tool's bottleneck is parsing and processing text, you drop into a faster language and the wins are real.

Here's what actually changed, what matters for shipping work, and what I'd upgrade today versus leave alone.

The speed story, in plain terms

An Astro build does two jobs. First it bundles your pages, content, and components into JavaScript. Then it runs that bundle like a tiny server, hits every page, and saves the HTML. Astro 7 made both faster, but went hardest at the bundling step, because that's where the time goes on large sites.

The numbers from the team's benchmarks (run on an M4 Pro Mac) tell the story:

  • The Astro docs site (~6,313 pages): 114.54s → 73.53s
  • astro.build itself (~308 pages): 62.70s → 24.24s, more than 2x faster
  • Cloudflare's developer docs (8,431 pages): 386.89s → 261.94s
  • Tauri's site (7,117 pages): 86.12s → 55.33s

The pattern: sites where .astro files and Markdown make up most of the build see the biggest jump, because those are exactly the parts that moved to native code. A page-heavy docs site wins big. A small marketing site with ten pages won't notice much. Be honest about which one you're shipping before you expect a 60 percent cut.

A new compiler, written in Rust

Astro's .astro file format had a compiler written in Go. Version 7 replaces it with a full rewrite in Rust. On its own that change is worth about 6 percent on a big docs build, because compiling .astro files is rarely the slowest part. The Markdown processing and bundling usually dominate. But it stacks with everything else, and there's a behaviour change you need to know about.

The old Go compiler quietly "fixed" your HTML. It reordered elements, auto-closed tags, and moved nodes around to make valid markup, which sometimes produced bugs that were a pain to track down. The new compiler stops doing that. It treats your markup as written. Three things to watch:

  • No more silent HTML correction. What you write is what you get.
  • JSX-style strictness. An unclosed tag like <div>Hello or a broken attribute like <div class="Hello > now throws an error instead of being patched over. These were always bugs, you just didn't see them.
  • Whitespace collapses like JSX. Newlines between inline elements no longer render as a space. So two <span> tags on separate lines render as "HelloWorld", not "Hello World". To keep the space, add {' '} between them.

That last one will bite a few people on upgrade. If text suddenly looks glued together, that's why.

Markdown moved to Rust too, and this is the big win

The headline change for content sites is Sätteri, a Rust-powered Markdown and MDX processor built by an Astro core team member. It's now the default. Switching the Astro and Cloudflare docs to it shaved over a minute off each build.

The old pipeline ran on unified (remark, rehype, and a long tail of JavaScript plugins). For every Markdown file, it parsed the text in JavaScript, walked the whole document tree once per plugin, then serialised back to HTML. On thousands of pages, that was often the slowest phase of the entire build. Sätteri does the parsing in native Rust and skips the work where it can.

There's a bonus: a pile of features that used to need separate plugins are now built in. Tables, footnotes, strikethrough, and task lists work out of the box. So do smart punctuation, heading IDs, container directives like :::note, math, frontmatter, and even wikilinks. If your config had five remark plugins just to get standard Markdown features, you can probably delete most of them.

Non-default features turn on through a features option:

import { defineConfig } from 'astro/config';
import { satteri } from '@astrojs/markdown-satteri';

export default defineConfig({
  markdown: {
    processor: satteri({
      features: {
        directive: true,
        math: true,
        headingAttributes: true,
      },
    }),
  },
});

If you depend on specific remark or rehype plugins that Sätteri doesn't cover, the old unified pipeline is still there. You opt back into it with @astrojs/markdown-remark. So nobody gets stranded, you just don't get the speed unless you switch.

Queued rendering is now the default

The rendering engine that turns components into HTML strings got replaced. The old approach was recursive: to render a component, you called the same render function on each of its children, which called it on their children, all the way down. The new engine uses a queue and a single loop. It pushes child nodes onto a stack in the right order and drains the stack until it's done.

The team clocks it at roughly 2.4x faster, though with a caveat worth repeating: the savings show up on pages dense with expressions. A page that's mostly static markup won't see much. It also uses less memory than the recursive version, which matters when you're rendering thousands of pages in one process.

Vite 8 and the new bundler under the hood

Astro 7 sits on Vite 8, which ships Rolldown, a Rust-based bundler that replaces both esbuild and Rollup with one tool. Rolldown benchmarks 10 to 30x faster than Rollup while keeping the same plugin API. For most projects this needs zero config changes. Vite 8 includes a compatibility layer that converts your old esbuild and Rollup options to their Rolldown equivalents, and custom Vite plugins should keep working because the plugin API didn't change.

This is the part I'd worry least about. It's a swap underneath you. If you have unusual custom plugins, test before you ship, but most sites just get faster for free.

Advanced Routing: full control over the request pipeline

This one isn't about speed, it's about power. Astro grew middleware, redirects, rewrites, Actions, sessions, and i18n over time, and stacking all of them made the request lifecycle hard to control. If you needed auth to run before Actions, or wanted to time only page rendering, you fought the pipeline instead of arranging it.

Astro 7 lets you take over by adding a src/fetch.ts file. It uses the standard fetch handler pattern from Cloudflare Workers, Deno, and Bun. You can forward some routes to a backend API and fall through to Astro for the rest:

import { astro, FetchState } from 'astro/fetch';

export default {
  fetch(request: Request) {
    const state = new FetchState(request);

    if (state.url.pathname.startsWith('/api')) {
      const url = new URL(state.url.pathname + state.url.search, 'https://backend-api.example.com');
      return fetch(new Request(url, request));
    }

    return astro(state);
  }
}

It's also compatible with Hono, so you can compose Astro's own features (i18n, actions, middleware, pages) as separate steps and put your auth or timing code exactly where it belongs. If you've ever been annoyed that your auth check ran after Actions, this fixes it. And if you don't add the file, nothing changes. Astro behaves exactly as before.

Route caching went stable, with CDN providers

Caching server-rendered responses has always been a mess because every host does it differently. Astro 7 makes route caching stable: one API, set cache directives in your routes, and Astro handles the rest wherever you deploy. You configure a provider once, then use Astro.cache.set() in a page with a maxAge, a stale-while-revalidate window, and tags for targeted invalidation. You can also set rules per route group in config and keep caching out of your page code entirely.

New in 7 are experimental CDN providers for Netlify, Vercel, and Cloudflare. Instead of holding responses in memory, they push your caching rules down to the host's edge network, so cache hits are served straight from the CDN without even invoking your server function. The Cloudflare one needs a feature that's in private beta, so leave it alone for now. Netlify and Vercel you can try.

The fastest build, after all, is the one that doesn't happen. Caching is how you stop rebuilding pages that didn't change. Worth setting up if you run on-demand rendering.

The AI tooling additions

Astro 7 adds features aimed squarely at coding agents, and they're genuinely useful even if you don't use agents much.

The big one is astro dev --background. AI agents struggle with long-running processes: a dev server never exits, so agents hang, spawn duplicates, or leave zombie processes behind. Background mode starts the dev server as a managed process, blocks until it's ready, prints the URL and process ID, then detaches. A lockfile stops duplicate instances. You check it with astro dev status and stop it with astro dev stop, from any shell. Astro can even detect when it's running inside an agent and turn this on automatically.

Honestly, that's handy for humans too. I've left enough orphaned dev servers running to appreciate a status-and-stop command.

The other addition is JSON logging, which was the most upvoted request on Astro's roadmap. The old logs were built for human eyes: colours, box-drawing characters, multi-line errors. None of that parses cleanly into a log aggregator. Now you run astro dev --json or configure structured logs, and you can pipe them into Kibana, CloudWatch, or Grafana. You can even compose loggers to keep readable console output while writing JSON for your tools.

What I'd actually do

Here's my upgrade call after reading through it all:

  1. Run the upgrade tool on a branch. npx @astrojs/upgrade handles the version bumps. Don't do it on main.
  2. Build and look for glued-together text. The JSX whitespace change is the most likely surprise. If two inline elements lost their space, add {' '}.
  3. Check your Markdown renders right. Sätteri is the default now. Most sites are fine, but if you leaned on specific remark or rehype plugins, confirm they're covered or switch back to the unified pipeline.
  4. Trim dead plugins. If you had remark plugins just for tables, footnotes, or heading IDs, Sätteri does those natively. Delete them.
  5. Leave the experimental CDN providers alone unless you're ready to test, and skip the Cloudflare one entirely until its beta opens.

The risk on this upgrade is low and the payoff is real if you ship content-heavy sites. Speed wins like this are the opposite of the tech debt you can't see: they're measurable, they compound, and the team did the hard work in Rust so you don't have to. If you're already weighing Rust-shaped tradeoffs in your own stack, my notes on Rust-inspired TypeScript habits cover where that thinking pays off in everyday code.

FAQ

Frequently asked

Mostly no, but there are a few. The new Rust compiler is stricter: unclosed tags and broken attributes now error instead of being silently fixed, and whitespace between inline elements collapses like JSX, so you may need {' '} to keep spaces. Sätteri replacing the default Markdown pipeline can also affect output if you relied on specific remark or rehype plugins. Run npx @astrojs/upgrade on a branch and test before merging.

The team's benchmarks show 15 to 61 percent faster overall, with some sites more than twice as fast. The catch is that the gains are concentrated. Sites where .astro compilation and Markdown processing dominate the build (large docs sites, content-heavy blogs) see the biggest cuts. A small site with a handful of pages won't see much difference, because its bottleneck was never the parts that moved to Rust.

For most projects, no. Vite 8 includes a compatibility layer that converts old esbuild and Rollup options automatically, and custom Vite plugins keep working on the same plugin API. Sätteri and queued rendering are the new defaults, so you get them without config. You only touch config to opt into non-default Markdown features, switch back to the unified pipeline, or set up route caching.

Sätteri is a Rust-powered Markdown and MDX processor that's now Astro's default. It uses pulldown-cmark for CommonMark parsing and Oxc for MDX, both native Rust, with platform binaries and a WASM fallback. It builds in features that used to need separate plugins: GFM tables, footnotes, smart punctuation, heading IDs, directives, math, frontmatter, and wikilinks. On large docs sites it shaved over a minute off build time.

The Netlify and Vercel providers are experimental but usable: they push your cache directives to the host's edge so hits skip your server function entirely. The Cloudflare provider needs a Workers feature that's in private beta, so don't use it yet. During the experimental phase you add providers manually; a future release will enable them automatically.

A src/fetch.ts file that hands you full control of Astro's request pipeline using the standard fetch handler pattern from Cloudflare Workers, Deno, and Bun. You can forward some routes to a backend, run auth before Actions, time only page rendering, or bring in Hono middleware. If you don't add the file, Astro behaves exactly as it does today, so it's opt-in with no downside.

Enjoyed this? Let's talk.

Start a conversation →