Deno Fresh vs Astro — which framework wins in 2026?
Astro is the safer default for most sites in 2026. Fresh 2.x wins on edge cold-start if your team lives in Deno — but ecosystem immaturity is the real cost.
By Ethan
1,832 words · 10 min read
Astro is the lower-risk choice for most content-heavy sites in 2026. The ecosystem depth, CMS integrations, and battle-tested static generation make it the obvious default. Fresh 2.x wins if your team already lives in Deno and edge cold-start latency is a hard requirement — the 9–12× boot improvement in Fresh 2.3.3 is real, but you will pay in ecosystem immaturity.
Who this is for
Developers choosing between two island-architecture frameworks for a content-heavy site that deploys to the edge. If you’re already decided on a Node.js-based stack, this comparison isn’t for you — Fresh’s value proposition is almost entirely tied to its Deno runtime. If you’re building a documentation site or CMS-driven blog that will never need a runtime, check Astro vs Eleventy instead.
What we tested
Deno Fresh 2.3.3 (released 2026-04-28 — the first stable build after 2.x migration completed 2025-09-09) against Astro 6.3.1 (May 2026). Test workload: a 5-page content site with one dynamic route — a server-rendered product listing page backed by a mock API. Deployed to Cloudflare Workers for the SSR benchmarks. Cold-start numbers for Fresh are self-reported by the Deno team (Fresh 2.0 beta announcement). No independent third-party benchmark comparing the two tools is publicly available as of May 2026 — methodology is noted per claim.
Island architecture
Both frameworks ship zero JavaScript to the browser by default. That is where the similarity ends.
Fresh uses an islands/ directory convention. Any component placed there gets hydrated; everything else is server-rendered HTML. Preact is the built-in UI library. As of Fresh 2.3+, pages with no islands serve absolutely no JavaScript — not even a runtime shim. If you are building a documentation site or a marketing page and want a verifiable zero-JS bundle, Fresh delivers it without configuration.
Astro uses client:* directives on individual components. The same zero-JS default applies, but the hydration model is richer:
client:load— hydrate immediately on page loadclient:idle— hydrate when the browser is idleclient:visible— hydrate when the component enters the viewportclient:media— hydrate when a CSS media query matches
Fresh has one hydration mode: the island loads. That is enough for most use cases, but Astro’s client:visible is meaningfully useful for below-the-fold interactive content — carousels, FAQ accordions, deferred comment sections.
The other structural difference: Astro supports React, Vue, Svelte, Solid, and Preact inside a single project. You can mix component frameworks per page. Fresh is Preact-only. That lock-in is fine if your team writes Preact, but it is a meaningful constraint if you are evaluating frameworks for a team that already has React components it wants to reuse.
Developer experience
Fresh 2.x is genuinely pleasant if you’re willing to work in Deno. The project initializes with one command — no npm, no Node.js required:
deno run -Ar jsr:@fresh/init
Fresh 2.0 introduced Vite-powered HMR, an Express/Hono-like App API, and fixed the async component rendering bugs that made 1.x brittle on dynamic routes. The Deno runtime enforces permissions at startup (-A grants all; production code scopes them explicitly), which is a real security advantage for server-rendered routes that call external APIs.
Astro requires Node.js and npm/pnpm/yarn. The setup surface is larger. The payoff is a mature toolchain: content collections with Zod-validated frontmatter, MDX support, a rich component model, and first-class TypeScript — no deno.json quirks, no Deno-specific import maps to explain to new contributors. The Astro 6 dev server now runs the workerd runtime for Cloudflare Workers targets, so “it worked in dev, broke in prod” bugs are largely gone.
One concrete DX win for Astro: the content collections API. If you are building a site with structured Markdown — blog posts, changelogs, docs pages — Astro’s getCollection() + Zod schema validation is substantially faster to work with than Fresh’s file-based routing plus manual front matter parsing. Fresh has no equivalent.
Build output and bundle size
For pure static output, neither framework produces significant JavaScript without islands. The meaningful comparison is the island runtime.
Astro bundles the React, Vue, or Preact runtime once as a shared chunk — roughly 30 KB min+gzip for Preact, ~45 KB for React. That chunk is amortized across all islands on the page. Two islands on a page do not double the runtime cost.
Fresh ships with Preact. A page with one island costs approximately the same as Astro with Preact — the runtimes are the same library. The difference is that Astro’s build pipeline applies tree-shaking and code splitting across the whole project. Fresh’s Vite integration (added in 2.0) narrows the gap, but Astro’s years of build optimization are reflected in final bundle sizes.
For static sites with no SSR, Astro also supports output: 'static' with no adapter — the output is plain HTML that deploys to any CDN. Fresh requires Deno to serve; there is no static export mode as of Fresh 2.3.3.
Cloudflare Workers deployment
This is where both frameworks converged in 2025–2026, and where the comparison gets specific.
Fresh 2.x on Cloudflare Workers requires:
@cloudflare/vite-pluginandwranglerin the project- A custom
server.jsthat exports afetchhandler - A
wrangler.tomlpointing at the built entry point
Fresh’s Deno-native server model maps cleanly to the Workers fetch handler — the abstraction is thin and the resulting Worker is small. The 9–12× cold-start improvement in Fresh 2.3.3 (self-reported by the Deno team: 86ms → 8ms, published in the Fresh 2.0 beta announcement) is the headline number. Workers bills on CPU milliseconds, so a faster cold start has real cost implications at scale.
Astro 6 on Cloudflare Workers uses @astrojs/cloudflare adapter v13. The adapter dropped Cloudflare Pages SSR support in v13 — SSR routes now deploy to Workers, not Pages. astro dev runs the real workerd runtime, so local development is production-parity. For step-by-step deployment, see How to Deploy Astro to Cloudflare.
Static Astro sites (no SSR adapter) still deploy to Cloudflare Pages via git push — that path is unchanged.
The practical implication: both tools now target the same Cloudflare Workers runtime for SSR. The configuration overhead for Fresh is lower (Deno’s runtime model was designed for this environment). The Astro adapter is more mature and has more documented edge cases, but it also introduces more moving parts.
Ecosystem and integrations
This is Fresh’s weakest point relative to Astro.
Astro has hundreds of integrations: Contentful, Sanity, Storyblok, Notion via Content Layer loaders; Pagefind and Algolia for search; Cloudinary and Imagetools for image optimization; Tailwind, UnoCSS, and vanilla-extract for styling. The community ships adapters and loaders at a pace that reflects the framework’s 59,000+ GitHub stars (as of May 2026).
Fresh gained access to the Vite plugin ecosystem in 2.0 — a meaningful improvement over 1.x, which was isolated from the broader JavaScript tooling ecosystem. But specific Fresh 2.x connectors for Contentful, Sanity, or Storyblok are not officially published as of May 2026. You can pull CMS data in a Fresh handler or route — it is plain Deno/TypeScript — but you are wiring it yourself rather than consuming a maintained integration.
The stars gap is stark: withastro/astro has roughly 59,000 GitHub stars; denoland/fresh has approximately 12,000. Contributor velocity, community plugins, and Stack Overflow coverage all track the star counts.
If your site will pull content from a headless CMS, needs full-text search, or depends on image optimization, Astro’s ecosystem advantage is decisive.
Deno tradeoffs
Fresh’s runtime is both its best feature and its biggest adoption barrier.
On the upside: Deno enforces permissions at the process level (file, network, environment). For server-rendered routes that call third-party APIs, that is a meaningful security boundary. Deno’s built-in TypeScript execution — no transpilation step, no ts-node — removes a layer of toolchain from the project. And JSR (Deno’s package registry) is maturing; the standard library is stable and well-documented.
On the downside: your team needs to understand Deno-specific tooling. deno.json import maps, permission flags, and the difference between npm and JSR packages are not steep learning curves individually, but they add up. Any contractor or new hire familiar with Node and npm will need onboarding. The Deno compatibility layer (npm: prefix imports) handles most npm packages, but occasionally you hit a package that assumes Node.js APIs that Deno doesn’t expose.
Astro runs on Node. Node runs everywhere. That mundane fact is not nothing.
Verdict
Pick Fresh 2.x if:
- Your team already writes Deno and you want to stay in that ecosystem.
- Cold-start latency on Cloudflare Workers is a hard requirement — 8ms is meaningfully better than typical Node.js cold starts.
- You want a zero-JS guarantee without configuration — the
islands/convention makes it structural rather than optional. - Your site is Preact-only and you won’t need to reuse React or Vue components.
- You are comfortable building CMS integrations yourself rather than consuming a maintained connector.
Pick Astro if:
- Your team writes TypeScript on Node.js and you want the path of least resistance.
- Content lives in a headless CMS (Contentful, Sanity, Storyblok, Notion) and you want an official loader, not a custom fetch.
- You need richer hydration strategies —
client:visibleandclient:mediahave real use cases on content-heavy pages. - Your project might need React, Vue, or Svelte components — Astro supports them all; Fresh does not.
- You are building a static site with no server-side logic and want
output: 'static'with no runtime dependency. - Ecosystem size matters for long-term maintenance: more plugins, more examples, more community support.
For most teams evaluating these tools in mid-2026, that verdict lands clearly on Astro. Fresh is a strong framework — its 2.x rewrite addressed the pain points that held 1.x back — but it asks you to commit to the Deno ecosystem in exchange for its advantages. That trade is worth it for a Deno-native team. For everyone else, Astro gives you the same island architecture with less friction and a deeper ecosystem.
Caveats
The Fresh cold-start numbers (9–12×, 86ms → 8ms) are self-reported by the Deno team in the Fresh 2.0 beta announcement. No independent third-party benchmark comparing Fresh and Astro on the same Cloudflare Workers account and workload is publicly available as of May 2026. Run your own measurements before treating the ratio as a contract.
Astro’s exact headline version at publication is 6.3.1 (May 2026). Features change across minor releases — verify at astro.build/blog before acting on specific behavior described here.
Fresh CMS integration status changes quickly. Verify what is available on JSR and the Deno module registry at time of writing before concluding you must build your own.
The article contains affiliate links to Cloudflare Workers. toolchew earns a commission if you sign up through those links.