The Road to Next — your interactive course for Next.js with React

Was Gatsby's GraphQL Data Layer a Mistake?

Robin Wieruch

When I migrated my blog to Gatsby in 2019, the GraphQL data layer was the part I evangelized hardest. By 2023, it was the part I was happiest to leave behind.

Was Gatsby’s choice to put GraphQL between every data source and every component a mistake? Yes. Elegant on a slide, expensive in practice. Read on for what it got right, what it got wrong, and what replaced it.

Gatsby’s Big Bet on GraphQL

In 2017 and 2018, Gatsby made a striking architectural call. Every data source (markdown files, images, a Contentful CMS, a Shopify store, a remote API) would flow into a single GraphQL schema, and every page or component would pull from that schema with a query.

You can see why this looked clever at the time. REST sources were inconsistent. Static-site generators like Jekyll and Hugo had their own opaque pipelines. Gatsby said: one query language, one schema, one mental model, no matter where the data lives. Source plugins on one side, page queries on the other, GraphiQL in the middle to explore the whole thing at localhost:8000/___graphql.

For a 2018 React developer, this was genuinely new. Type-aware queries against your own filesystem felt magical the first time you ran a query against your blog posts and got back exactly the fields you asked for.

What the GraphQL Data Layer Got Right

It would be unfair to write the whole bet off. A few things Gatsby’s data layer pioneered are now table stakes in modern frameworks:

One mental model across heterogeneous sources. Whether the data came from gatsby-source-filesystem, gatsby-source-contentful, or gatsby-source-graphql (a remote API), the consumer side looked identical: a query in a component, fields out. The plugin handled the awkward bits.

Co-located queries. A page component declared the data it needed in the same file. The graphql template tag sat next to the JSX that used the result. React Server Components in Next.js have arguably re-discovered this idea, just without the GraphQL.

An explorable schema. GraphiQL at localhost:8000/___graphql was a killer feature. Hit a question, run a query, see the shape, paste it into your component. That feedback loop is genuinely good developer ergonomics.

Resolver power for content transforms. gatsby-transformer-sharp exposed childImageSharp resolvers off any image node, so you queried responsive image sources right out of GraphQL. The composability was real.

Why It Was a Mistake in Hindsight

So why did I migrate away, and why is it fair to call the architecture a mistake?

1. Build times that grew with the schema. Every data source you added inflated the schema. Every plugin you installed ran transforms at build. A markdown blog with images and a CMS hit minute-long builds quickly, and small content edits could trigger full rebuilds. By contrast, a fresh Astro site with the same content rebuilds in under a second.

2. A learning tax for trivial sites. To render markdown files, the official tutorial taught you to install gatsby-source-filesystem and gatsby-transformer-remark, write a gatsby-node.js with createPages, define a page-query template, and use useStaticQuery for site metadata. Astro’s equivalent is one line: getCollection('posts').map(...). Gatsby itself acknowledged the problem in 2018 with a blog post titled “Using Gatsby without GraphQL”, a tacit admission that the data layer was sometimes a tax, not a feature. The escape hatch came with strings: skip the GraphQL layer and you also skip Gatsby’s image optimization and several plugin features.

3. Schema inference that wasn’t deterministic. Gatsby inferred GraphQL types from the data it found at build. If no node happened to have an optional field, the field disappeared from the schema. If two nodes mixed types, the schema collapsed. Gatsby itself wrote, in 2019, that “changes to the data could cause changes to the schema, which could cause breakage in unrelated locations. Those bugs were confusing and hard to debug.” The fix was schema customization with createTypes and SDL directives like @dontInfer, which introduced its own learning curve.

4. Type safety arrived five years late. The whole promise of GraphQL has always been typed queries. End-to-end TypeScript types generated from your queries did not ship in Gatsby until v5, in January 2023, five years after the data layer launched. By the time you could trust the types, most teams had moved on.

5. Plugin breakage on every major version. The gatsby-image to gatsby-plugin-image migration in v3 ate days. GraphQL fragments were removed and replaced with resolver arguments. fluid became fullWidth or constrained. A codemod helped, not enough. Every Gatsby major version brought a “which plugins are still maintained?” audit, and third-party source plugins for CMSes were the first to rot.

6. A second build system in gatsby-node.js. createPages, onCreateNode, createSchemaCustomization. Gatsby’s data layer required you to write Node.js code that mutated a node store at build time. Astro’s getStaticPaths() and Next.js’s generateStaticParams cover the same ground without asking you to learn a node-store mutation API.

The honest summary: Gatsby’s GraphQL layer was elegant in isolation and a poor architectural commitment given how the rest of the web moved. Server Components, file-based content collections, and typed loaders cover the same ground without making GraphQL the price of entry.

If You’re Still Maintaining a Gatsby Site

If you landed here because you have a Gatsby site you didn’t choose to inherit, the practical bits still apply. Gatsby is on 5.16.x as of early 2026, in maintenance mode, but the data-layer APIs work as documented.

Page query vs useStaticQuery. A page component (anything in src/pages/ or used as a createPage template) can export a graphql query and receive data as a prop. Page queries accept variables from page context. Anything that isn’t a page should use the useStaticQuery hook: same query language, no variables.

<StaticQuery> is deprecated. As of Gatsby 5, the <StaticQuery> component is officially deprecated and will be removed in Gatsby 6 (whenever that ships). If your codebase still uses it, replace each instance with useStaticQuery. Same data, less code.

Fragments still work. The fragment AuthorInfo on AuthorEntry { ... } pattern is unchanged, and Gatsby preprocesses all GraphQL queries during compilation, so you don’t import them. They are available globally by name. Worth using for any field set you read in three or more places.

GraphiQL at localhost:8000/___graphql. This is still the right tool. The standalone GraphQL Playground project that older posts (including this one’s earlier version) used to recommend was merged into GraphiQL under the GraphQL Foundation back in 2020 and has not shipped a release since 2019. Stick with what Gatsby ships out of the box.

What Replaced It

If you’re starting a new project in 2026, none of these problems are yours to solve. The frameworks I’d reach for instead:

Astro for content-driven sites. Content collections give you typed access to markdown and MDX with one config file: defineCollection({ loader: glob({...}), schema: z.object({...}) }), then getCollection('posts') in a page. Zod for validation, full TypeScript inference, no GraphQL layer to learn. This blog runs on Astro now.

Next.js for full applications. The App Router lets you write export default async function Page() { const data = await fetch(...) }: async server components that just fetch. No GraphQL layer, no gatsby-node.js, no schema. Generate static params for dynamic routes when you want SSG; let the route render at request time when you don’t.

TanStack Start if you want first-class type safety and explicit, router-attached data loaders. Currently in release-candidate phase, not yet 1.0, but worth watching if you’re starting something today.

Each of these solves the data-sourcing problem Gatsby solved, without making GraphQL the price of entry. That’s the part that aged badly.


Gatsby’s GraphQL data layer was the right answer to a question the web was asking in 2018, and the wrong commitment to ride into 2026. If you’re still on a Gatsby site, the docs and APIs work, but the surrounding ecosystem won’t keep up forever.

If you’re considering Gatsby for something new, start with the question one level up first.

Read More
Is Gatsby still worth using in 2026?

Never Miss an Article

Join 50,000+ developers getting weekly insights on full-stack engineering and AI.

AI Agentic UI Architecture React Next.js TypeScript Node.js Full-Stack Monorepos Product Engineering
Subscribe on Substack

High signal, low noise. Unsubscribe at any time.