Skip to main content

Gatsby vs Astro: Legacy SSG vs Modern Island Architecture

·PkgPulse Team

The Great Gatsby Exodus is no longer a prediction — it's a migration already underway. Gatsby dominated static site generation from 2018 to 2022. It popularized React-based static sites, introduced the content mesh concept, and built an ecosystem of 2,500+ plugins. Then developers started shipping their Gatsby sites on Astro and watching build times drop from minutes to seconds, JavaScript payloads shrink from 200+ KB to under 5 KB, and Lighthouse scores climb to near-perfect without a single optimization pass.

Gatsby isn't dead, but its trajectory is clear. Netlify's acquisition in 2023 was followed by reduced investment, core team departures, and a plugin ecosystem where many of the most popular packages haven't been updated in over a year. Meanwhile, Astro was acquired by Cloudflare in January 2026 — a strong signal of long-term backing and infrastructure-level commitment.

We compared both frameworks using real data from PkgPulse. Here's what the numbers say.

TL;DR

Astro ships 40x less JavaScript, builds 40 pages 10x faster, and scores near-perfect on Core Web Vitals out of the box. Gatsby still requires full React hydration on every page, GraphQL for all data fetching, and a build pipeline that slows down exponentially with page count. Unless you're maintaining a highly interactive React SPA that depends on Gatsby's content mesh, Astro is the better choice in 2026 — and Gatsby's own React components can come with you.

Key Takeaways

  • Astro ships ~5 KB of JavaScript by default. Gatsby ships 200+ KB (full React runtime + framework code) on every page, even purely static ones.
  • Build times aren't comparable. A real 40-page site migrated from Gatsby (2 minutes 45 seconds) to Astro (under 50 seconds) — a 3.3x improvement, and the gap widens with page count.
  • Gatsby requires GraphQL for data fetching. Astro uses standard ESM imports, import.meta.glob(), and getCollection() — no query language overhead.
  • Astro supports React components natively. Existing Gatsby React components can be reused in Astro with minimal changes, making migration practical rather than theoretical.
  • Gatsby's ecosystem is declining. Many popular plugins are unmaintained. Astro's ecosystem is smaller but growing rapidly with active maintenance.
  • Cloudflare acquired Astro (January 2026). Gatsby's future under Netlify remains uncertain with reduced investment.

At a Glance

MetricGatsbyAstro
Default JS Shipped200+ KB (full React runtime)~5 KB (interactive islands only)
JS ReductionBaseline~40x less than Gatsby
Build Time (40 pages)2-3 minutes~10 seconds
Hydration ModelFull SPA hydration (every page)Islands (selective, opt-in)
Data FetchingGraphQL (required)ESM imports, glob, getCollection()
Framework SupportReact onlyReact, Vue, Svelte, Solid, Preact
Core Web Vitals70-85 Lighthouse (typical)95-100 Lighthouse (default)
ArchitectureSPA with static pre-renderingMPA with static-first rendering
Corporate BackingNetlify (reduced investment)Cloudflare (acquired Jan 2026)
Plugin Ecosystem2,500+ (many unmaintained)Smaller, actively maintained

See the full live comparison — download trends and health scores — at pkgpulse.com/compare/astro-vs-gatsby

The headline: Astro ships 40x less JavaScript and builds content sites 10x faster. Gatsby's SPA architecture forces every page to pay the cost of React hydration, even when there's nothing interactive on the page.

Architecture: SPA Hydration vs. Islands

The fundamental difference between Gatsby and Astro isn't about features or syntax — it's about how each framework thinks about JavaScript in the browser.

Gatsby: Every Page Is a React App

Gatsby pre-renders pages to static HTML at build time, but then re-hydrates the entire page as a React single-page application on the client. The browser downloads the HTML (fast initial paint), then downloads and executes the React runtime, the Gatsby framework code, your component tree, and the client-side router.

// A simple Gatsby blog post page
// This ships 200+ KB of JavaScript to the browser
// even though there's nothing interactive on the page

import React from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"

export default function BlogPost({ data }) {
  const post = data.markdownRemark
  return (
    <Layout>
      <h1>{post.frontmatter.title}</h1>
      <div dangerouslySetInnerHTML={{ __html: post.html }} />
    </Layout>
  )
}

export const query = graphql`
  query($slug: String!) {
    markdownRemark(fields: { slug: { eq: $slug } }) {
      html
      frontmatter { title }
    }
  }
`

That blog post is static text. There are no event handlers, no client-side state changes, no interactive elements. But the browser still downloads, parses, compiles, and executes 200+ KB of JavaScript to "hydrate" the page — recreating the React component tree in memory so that client-side navigation and React's reconciliation can work.

The result: a visible gap between First Contentful Paint (fast, because static HTML) and Time to Interactive (slower, because the page isn't "ready" until React finishes hydrating). On slower devices and connections, that gap can stretch to several seconds.

Astro: JavaScript Is Opt-In

Astro takes the opposite stance. Pages are static HTML by default. JavaScript only ships to the browser when you explicitly mark a component as interactive.

---
// This page ships ZERO JavaScript by default
import Layout from '../layouts/Layout.astro';
import BlogPost from '../components/BlogPost.astro';

// Only SearchBar gets JavaScript — and only when scrolled into view
import SearchBar from '../components/SearchBar.jsx';

const post = await getEntry('blog', Astro.params.slug);
---

<Layout>
  <BlogPost post={post} />
  <SearchBar client:visible />
</Layout>

The client:visible directive tells Astro to load SearchBar's JavaScript only when the user scrolls it into view. The rest of the page — the layout, the blog post content, the navigation — is pure HTML. No React runtime, no hydration, no JavaScript parsing.

Astro's hydration directives give you fine-grained control:

  • client:load — hydrate immediately on page load
  • client:idle — hydrate when the browser is idle
  • client:visible — hydrate when the component scrolls into view
  • client:media — hydrate at a specific CSS media query

Every byte of JavaScript is a deliberate choice. A 20-page marketing site with one interactive form might ship 15 KB total. The same site in Gatsby ships 200+ KB on every single page.

Performance Head-to-Head

Build Times

ScenarioGatsbyAstro
40-page content site2 min 45 secUnder 50 seconds
Same site (simplified)~3 minutes~10 seconds
Scaling behaviorExponential slowdownNear-linear

A real-world migration tells the story clearly: a 40-page site that took Gatsby 2 minutes and 45 seconds to build completed in under 50 seconds on Astro. That's a 3.3x improvement — and the gap grows with page count.

Gatsby's build pipeline does significant work: running GraphQL queries, generating the React component tree, code-splitting, creating the client-side route manifest, and optimizing JavaScript bundles. Astro's pipeline is simpler — it compiles pages to static HTML and only processes JavaScript for explicitly interactive components.

For sites with hundreds of pages, the difference becomes severe. A 500-page docs site that takes Gatsby 8-10 minutes might build in under 2 minutes on Astro. Developer iteration speed improves proportionally.

JavaScript Shipped

MetricGatsbyAstro
Baseline JS (static page)200+ KB0 KB
Page with one interactive widget200+ KB~5-15 KB
JS reductionBaseline~40x less
React runtime includedAlwaysOnly for React islands

Gatsby's 200+ KB baseline includes the React runtime (~42 KB gzipped), ReactDOM (~130 KB pre-gzip), Gatsby's framework code, the client-side router, and the page data JSON. This ships on every page regardless of interactivity.

Astro's baseline is 0 KB. If you add a React island, Astro ships React's runtime only for that component — and only the portion needed. A page with one small interactive React component might ship 15 KB total. The same page in Gatsby ships 200+ KB.

Largest Contentful Paint and Core Web Vitals

Core Web VitalGatsbyAstro
Largest Contentful Paint (LCP)Moderate (JS blocks rendering)Excellent (pure HTML)
Cumulative Layout Shift (CLS)Moderate (hydration shifts)Near-zero
Interaction to Next Paint (INP)Poor-moderate (hydration delay)Excellent (minimal JS)
Typical Lighthouse Score70-8595-100

Astro pages achieve 95-100 Lighthouse scores consistently because there's almost no JavaScript to interfere with rendering. The browser receives HTML, renders it, and the page is done. No hydration delay, no JavaScript-induced layout shifts, no event handler registration gap.

Gatsby pages typically land in the 70-85 range because the mandatory JavaScript payload affects every Core Web Vital. LCP is delayed by JavaScript blocking the main thread. CLS can occur when hydration triggers re-renders. INP suffers because event handlers aren't registered until hydration completes.

Data Fetching: GraphQL vs. ESM Imports

This is one of the most impactful developer experience differences — and one of the most common reasons developers cite for leaving Gatsby.

Gatsby: GraphQL or Nothing

Gatsby requires GraphQL for virtually all data fetching. Want to query your Markdown files? GraphQL. Pull from a CMS? GraphQL. Access site metadata? GraphQL. Even reading a JSON file goes through the GraphQL data layer.

// Gatsby: fetching a list of blog posts requires a GraphQL query
export const query = graphql`
  query BlogListQuery {
    allMarkdownRemark(sort: { frontmatter: { date: DESC } }) {
      nodes {
        id
        frontmatter {
          title
          date(formatString: "MMMM DD, YYYY")
        }
        fields {
          slug
        }
      }
    }
  }
`

GraphQL is powerful for complex data relationships, but for most content sites, it's significant overhead. You learn a query language, debug query errors, manage GraphQL fragments, and navigate a data layer that adds abstraction between you and your content.

Astro: Standard JavaScript

Astro uses standard ESM imports, import.meta.glob(), and its content collections API. No query language. No data layer abstraction.

---
// Astro: fetching blog posts with standard JavaScript
import { getCollection } from 'astro:content';

const posts = (await getCollection('blog'))
  .sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf());
---

{posts.map(post => (
  <article>
    <h2>{post.data.title}</h2>
    <time>{post.data.date.toLocaleDateString()}</time>
  </article>
))}

Content collections provide type safety, schema validation, and a clean API — without the overhead of learning and debugging GraphQL. For developers who know JavaScript, data fetching in Astro feels like standard application code rather than a framework-specific abstraction.

You can also use import.meta.glob() for simpler file-based patterns, or fetch() for external APIs. No plugins required.

Migration Path: Gatsby to Astro

Astro provides an official migration guide from Gatsby, and the process is more practical than you might expect.

What Transfers Directly

  • React components. Astro supports React via @astrojs/react. Your existing Gatsby components can be used as Astro islands with minimal changes — primarily removing Gatsby-specific imports (Link, graphql, useStaticQuery) and replacing them with Astro equivalents.
  • Content files. Markdown and MDX files work in Astro with similar or identical frontmatter patterns.
  • Styling. CSS Modules, Tailwind, styled-components, and most CSS-in-JS approaches work in Astro.

What Changes

  • Page routing. Gatsby uses src/pages/ with React components. Astro uses src/pages/ with .astro files (or .mdx, .md). The file-based routing convention is similar, but the file format changes.
  • Data fetching. Replace graphql queries and useStaticQuery hooks with Astro's content collections, import.meta.glob(), or direct fetch() calls.
  • Dynamic pages. Replace gatsby-node.js createPages API with Astro's getStaticPaths() function.
  • Plugins. Gatsby plugins (image optimization, RSS, sitemaps) are replaced by Astro integrations. Most common use cases have Astro equivalents.

A Realistic Timeline

For a 40-page content site with moderate complexity:

  • Simple blog/docs: 1-2 weeks for a full migration
  • Marketing site with interactive components: 2-4 weeks
  • Complex site with many Gatsby plugins: 4-6 weeks

The biggest time investment is typically replacing GraphQL data fetching, not porting React components. If your components are well-isolated, they can often be dropped into Astro as islands with minimal modification.

Ecosystem Reality

Gatsby's Declining Ecosystem

Gatsby's plugin ecosystem was once its greatest strength. Over 2,500 plugins covered everything from image optimization to CMS integrations to analytics. But that ecosystem is now a liability:

  • Many popular plugins are unmaintained. Check the last commit date on Gatsby plugins you depend on — many haven't been updated in 12-18 months.
  • Core team has shrunk. After Netlify's acquisition, key contributors moved on. Development velocity has slowed significantly.
  • Plugin compatibility issues. Gatsby 5 introduced breaking changes, and many plugins never updated.
  • Community energy has shifted. New tutorials, blog posts, and conference talks about Gatsby have dropped sharply since 2023.

Astro's Growing Ecosystem

Astro's ecosystem is smaller but healthier:

  • Official integrations cover the most common needs: React, Vue, Svelte, Tailwind, MDX, sitemap, RSS, image optimization.
  • Active maintenance. Integrations are updated regularly and compatible with the latest Astro versions.
  • Cloudflare acquisition (January 2026) provides long-term financial stability and infrastructure integration.
  • Growing community. Active Discord, regular releases, and increasing adoption across the industry.
  • Starlight — Astro's official docs theme — has become one of the most popular documentation frameworks, demonstrating the platform's maturity for content-driven use cases.

The practical difference: when you encounter an issue with an Astro integration, you're likely to find recent GitHub issues, active maintainers, and current documentation. With many Gatsby plugins, you'll find stale issues and no response.

When Gatsby Still Makes Sense

Gatsby isn't the right choice for new projects in most cases, but there are scenarios where it remains viable:

  • Highly interactive React SPAs with content. If your site is more application than content — complex state management, extensive client-side interactivity, real-time features — and happens to have a content layer, Gatsby's full SPA architecture serves that use case.
  • Deep content mesh requirements. If you're aggregating data from many heterogeneous sources (multiple CMSes, databases, APIs) and need GraphQL's ability to stitch them into a unified schema, Gatsby's data layer is purpose-built for that.
  • Large existing Gatsby codebases. If you have a 500-page Gatsby site with dozens of custom plugins and a team that knows Gatsby deeply, the migration cost may outweigh the benefits — at least in the short term.
  • Legacy maintenance. If the site works, isn't growing, and doesn't need performance improvements, there's no urgent reason to migrate.

For these scenarios, Gatsby is functional. But note that even the "highly interactive SPA" use case is increasingly served by Next.js or Remix rather than Gatsby.

The Verdict

The data leaves little room for ambiguity. For content-driven websites — blogs, documentation, marketing sites, portfolios, landing pages — Astro is the better framework in 2026 by every measurable metric.

  • 40x less JavaScript shipped to the browser
  • 10x faster builds for comparable page counts
  • 15-30 point higher Lighthouse scores out of the box
  • Simpler data fetching without GraphQL overhead
  • Stronger long-term backing with Cloudflare's acquisition
  • Growing ecosystem vs. Gatsby's declining one

Astro lets you keep your React components, migrate incrementally, and end up with a faster site that's easier to maintain. The official migration guide makes the path concrete rather than aspirational.

Gatsby pioneered React-based static site generation and deserves credit for advancing the ecosystem. But the architecture decisions that made sense in 2018 — full SPA hydration, mandatory GraphQL, heavy JavaScript bundles — are exactly the problems that Astro was designed to solve.

If you're starting a new content site, choose Astro. If you're maintaining a Gatsby site and experiencing build time pain, JavaScript bloat, or poor Core Web Vitals, the migration is worth the investment.

Compare Gatsby vs Astro on PkgPulse →


Frequently Asked Questions

Should I migrate my Gatsby site to Astro?

If your Gatsby site is primarily content — a blog, documentation, or marketing pages — and you're experiencing slow builds, poor Lighthouse scores, or dependency issues with unmaintained plugins, migrating to Astro will solve those problems. A 40-page site that builds in 3 minutes on Gatsby can build in under a minute on Astro, with dramatically better performance. If your Gatsby site is a complex SPA that heavily leverages the GraphQL content mesh, evaluate whether the migration effort is justified by the performance gains. See the live comparison on PkgPulse for current data.

Can I use my existing Gatsby React components in Astro?

Yes. Astro has first-class React support via @astrojs/react. Your React components can be used as interactive islands in Astro pages. The main changes are removing Gatsby-specific imports (Link, graphql, useStaticQuery) and replacing them with Astro equivalents. Components that are purely presentational can often be converted to .astro components for zero JavaScript overhead, while interactive components can remain as React islands that hydrate selectively.

Is Gatsby dead?

Gatsby is not dead, but it is in decline. Development velocity has slowed significantly since Netlify's acquisition, many plugins are unmaintained, and community activity has dropped. The framework still works for existing sites and receives occasional updates, but the trajectory is downward. Most developers starting new static sites in 2026 are choosing Astro, Next.js, or other alternatives. Gatsby's niche — highly interactive React SPAs with complex content mesh requirements — is increasingly served by other frameworks.

Why does Astro ship so much less JavaScript than Gatsby?

The difference comes down to architecture. Gatsby pre-renders pages as static HTML, then re-hydrates the entire page as a React SPA — shipping the React runtime (200+ KB) on every page regardless of interactivity. Astro renders pages as static HTML and only ships JavaScript for components you explicitly mark as interactive with directives like client:load or client:visible. A page with no interactive components ships zero JavaScript. This "islands architecture" means JavaScript is proportional to actual interactivity, not a fixed tax on every page.


Compare live download trends, health scores, and ecosystem data for Gatsby and Astro on PkgPulse. Explore more framework comparisons in our comparison hub.

Comments

Stay Updated

Get the latest package insights, npm trends, and tooling tips delivered to your inbox.