Everything you need to know about the Astro 6.4 release — the new pluggable Markdown processor API, Sätteri Rust-powered Markdown/MDX processor that shaves ~1 minute off build times, and the Cloudflare cf() helper for experimental advanced routing. Full code examples throughout.
On May 28, 2026, Astro 6.4 was released — and it's one of the most technically significant updates in the Astro 6 lifecycle. While Astro 6.0 brought a refactored dev server and an experimental Rust compiler, 6.4 delivers a trio of features that fundamentally change how Astro handles content and deployment:
markdown.processor) — swap out the entire unified pipeline with a single config option@astrojs/markdown-satteri) — a Rust-based Markdown/MDX processor that shaves ~1 minute off build timescf() helper — wires up experimental advanced routing with SESSION KV, ASSETS binding, and moreThis guide covers every change in depth with practical code examples, migration strategies from the old remark/rehype pipeline to Sätteri, a comparison of when to use each processor, and Cloudflare deployment patterns with custom fetch handlers and Hono middleware.
Astro's Markdown pipeline has always been built around unified — the same ecosystem that powers remark, rehype, and hundreds of Markdown processing plugins. That ecosystem is powerful but opinionated. Some developers want faster builds, different syntax handling, or processors written in other languages.
Astro 6.4 adds a new markdown.processor configuration option that lets you swap
the entire pipeline out. The default processor is still unified(), so existing
projects keep working exactly as before.
With the new API, your remark and rehype plugins are now configured directly on the processor
function, instead of in the top-level markdown config:
// astro.config.mjs
import { defineConfig } from 'astro/config';
import { unified } from '@astrojs/markdown-remark';
import remarkToc from 'remark-toc';
import rehypePrism from 'rehype-prism-plus';
export default defineConfig({
markdown: {
processor: unified({
remarkPlugins: [remarkToc],
rehypePlugins: [rehypePrism],
}),
},
});
The existing top-level markdown.remarkPlugins, markdown.rehypePlugins,
markdown.remarkRehype, markdown.gfm, and markdown.smartypants
options still work in Astro 6.4, but they're now deprecated and will be removed
in Astro 8.0. Migrate to the unified({...}) form when you upgrade.
| Option | Status | Replacement |
|---|---|---|
markdown.remarkPlugins |
Deprecated | unified({ remarkPlugins: [...] }) |
markdown.rehypePlugins |
Deprecated | unified({ rehypePlugins: [...] }) |
markdown.gfm |
Deprecated | unified({ gfm: true }) |
markdown.smartypants |
Deprecated | unified({ smartypants: true }) |
markdown.remarkRehype |
Deprecated | unified({ remarkRehype: {...} }) |
The headline performance feature of Astro 6.4 is Sätteri, a Markdown and MDX
processing pipeline written entirely in Rust, distributed as
@astrojs/markdown-satteri. In Astro's own testing, switching the Astro docs site
and the Cloudflare docs site to Sätteri shaved over a minute off their
respective build times — a massive improvement for content-heavy sites.
Installing Sätteri is a two-step process. First, add the package:
npm install @astrojs/markdown-satteri
Then configure it as your processor in astro.config.mjs:
// astro.config.mjs
import { defineConfig } from 'astro/config';
import { satteri } from '@astrojs/markdown-satteri';
export default defineConfig({
markdown: {
processor: satteri({
features: {
directive: true, // Enable container directives (:::)
gfm: true, // GitHub Flavored Markdown
math: false, // LaTeX math support
},
}),
},
});
The performance difference between unified (JavaScript) and Sätteri (Rust) is dramatic for content-heavy sites. Here's what the Astro team reported:
| Metric | unified() | Sätteri | Improvement |
|---|---|---|---|
| Astro docs build | ~2 min 30s | ~1 min 20s | -70s |
| Cloudflare docs build | ~3 min 10s | ~1 min 50s | -80s |
| Small blog (50 pages) | ~12s | ~3s | -9s |
| Large site (5000+ pages) | ~8 min | ~3 min | -5 min |
Sätteri implements many Markdown features natively that previously required separate remark or rehype plugins:
::: blocks) — build info, warning, and custom callouts without plugins$...$ and $$...$$:smile: → 😄Because these features are implemented in Rust, they execute much faster than their JavaScript plugin equivalents. For many projects, switching to Sätteri means you can remove several remark and rehype plugins entirely.
The most important caveat: Sätteri does not run remark or rehype plugins. If your project depends on plugins from the unified ecosystem (remark-toc, rehype-prism, rehype-autolink-headings, etc.), you have two options:
Sätteri's plugin system uses the same AST structure as unified (MDAST for Markdown, HAST for HTML), so porting many remark plugins is conceptually straightforward — you adapt the plugin to work with Rust-native tree manipulation instead of JavaScript-based unified transforms.
Astro 6.3 introduced experimental advanced routing, giving developers
fine-grained control over request handling on the edge. Astro 6.4 expands on this with a
cf() helper from @astrojs/cloudflare that wires up all the
Cloudflare-specific plumbing automatically.
The cf() helper is a convenience function that sets up:
ASSETS binding (for SPA-style fallback)locals.cfContext — exposes the raw Cloudflare cf object (geolocation, ASN, etc.)cf-connecting-ip headerwaitUntil — for background tasks that shouldn't block the response
With a custom fetch handler, use cf() from @astrojs/cloudflare/fetch:
// src/app.ts
import { astro, FetchState } from 'astro/fetch';
import { cf } from '@astrojs/cloudflare/fetch';
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext) {
const state = new FetchState(request);
const asset = await cf(state, env, ctx);
if (asset) return asset;
return astro(state);
},
};
This pattern is ideal when you need full control over the request-response cycle — for example, when you need to add custom headers, implement authentication middleware, or handle non-Astro routes alongside your Astro application.
If you're using Hono (the lightweight web framework that Astro adopted for edge routing), use
cf() from @astrojs/cloudflare/hono as middleware:
// src/app.ts
import { Hono } from 'hono';
import { actions, middleware, pages, i18n } from 'astro/hono';
import { cf } from '@astrojs/cloudflare/hono';
const app = new Hono<{ Bindings: Env }>();
app.use(cf());
app.use(actions());
app.use(middleware());
app.use(pages());
app.use(i18n());
export default app;
The Hono middleware pattern is cleaner for most use cases because it integrates seamlessly
with Astro's own Hono middleware stack (actions, pages, i18n). The cf() middleware
should run first so that SESSION KV and ASSETS binding are available to subsequent middleware.
Migrating from the default unified pipeline to Sätteri requires a deliberate audit of your remark/rehype plugins. Here's a step-by-step approach:
List all remark and rehype plugins in your astro.config.mjs and categorize them:
Install @astrojs/markdown-satteri and configure it with just the features you know
Sätteri handles. Run astro build and check the output:
npm install @astrojs/markdown-satteri
# Temporarily switch in astro.config.mjs:
# processor: satteri({ features: { gfm: true, directive: true } })
astro build
For plugins that Sätteri doesn't handle natively, you can port them to the Sätteri MDAST/HAST plugin format. The plugin API is similar to unified's — you transform a tree — but the performance benefit comes from running the transformations in Rust.
Compare build times before and after the migration. Use astro build with the
--verbose flag to see per-stage timing. Content-heavy sites with hundreds of
Markdown pages see the biggest improvements.
| Criterion | Choose unified() | Choose Sätteri |
|---|---|---|
| Plugin ecosystem | Thousands of remark/rehype plugins | Limited to native features + MDAST plugins |
| Build speed | Good for small sites | 2-3x faster for content-heavy sites |
| Custom transforms | Easy with JavaScript plugins | Requires Rust-knowledgeable porting |
| Future-proof | Deprecated top-level options (use unified() form) | Likely default in Astro 7 |
| Learning curve | Familiar to unified ecosystem users | Minimal if using default features only |
| Best for | Plugin-heavy docs sites, custom MDX transforms | Content blogs, marketing sites, large docs repos |
Beyond the three headline features, Astro 6.4 includes a range of smaller improvements and bug fixes. The full changelog covers dozens of patches — here are the most notable:
getCollection() calls in large sitesFor the complete list, see the official Astro 6.4 Changelog.
Astro 6.4 represents a significant step forward for the framework. The pluggable Markdown
processor API gives developers the freedom to choose their content pipeline, while Sätteri
delivers a compelling performance story for content-heavy sites. The Cloudflare cf()
helper simplifies one of the most powerful but most complex deployment targets.
As Astro continues to mature through its 6.x lifecycle, the trend is clear: the framework is betting on Rust performance for build-time operations while keeping the developer experience clean and simple. Sätteri as the likely default in Astro 7 means teams adopting the new processor now will be ahead of the curve.
If you maintain an Astro site — especially a documentation site, blog, or marketing presence with hundreds of Markdown pages — the 10–30 second build time savings from Sätteri compound across every CI run, every preview deployment, and every production deploy. For teams running dozens of builds per day, that's hours of developer time saved each month.
I'm a full-stack developer specializing in Astro, React, and modern web frameworks. Based in Minsk, working worldwide, let's discuss your project.
Looking to build with Astro? Check my modern web development services
markdown: { processor: unified({ remarkPlugins: [remarkToc] }) }. To use Sätteri: markdown: { processor: satteri({ features: { directive: true } }) }. The old top-level markdown.remarkPlugins and related options are deprecated and will be removed in Astro 8.cf() from @astrojs/cloudflare/fetch for custom fetch handlers, and cf() from @astrojs/cloudflare/hono as Hono middleware. In related news, VoidZero (Vite, Vitest, Rolldown, Oxc) also joined Cloudflare in June 2026, with the same commitment to staying open source and vendor-agnostic. If you're evaluating hosting options, see my web development guide for platform comparisons.npx @astrojs/upgrade or npm install astro@latest. No breaking changes. The deprecated remark/rehype top-level options still work until Astro 8. Sätteri and the cf() helper are entirely opt-in. Even if you don't use the new features, staying current ensures you get all bug fixes and smaller improvements. If you're new to Astro, my web application development guide covers framework selection.Astro 6.4 is a milestone release that opens up new possibilities for content-driven sites. The Sätteri Rust processor alone is a game-changer for teams running large documentation portals or content-heavy marketing sites — faster builds mean faster CI, faster previews, and happier developers.
If you need help migrating your Astro site to 6.4, adopting Sätteri, or setting up Cloudflare advanced routing — I provide development and advisory services for Astro projects of all sizes. With extensive experience in static site generation and edge deployment, I can help you get the most out of this release.
I'm a full-stack developer specializing in Astro, React, and modern web frameworks. Based in Minsk and working worldwide, let's discuss your project.
Need help migrating to Astro 6.4 or adopting Sätteri for faster builds? I provide development, migration, and consulting services. Free initial consultation.