Sanity vs WordPress headless CMS: when headless actually beats traditional

May 20, 2026 · 7 min read

Choosing between Sanity and WordPress as a headless CMS is rarely a pure technical question. It involves editor habits, hosting budgets, plugin dependencies, and how much custom work you want to own long-term. I migrated a mid-size marketing site — 400 pages, 3 content editors, ~180k monthly visits — from WordPress (with WPGraphQL) to Sanity + Next.js earlier this year. The numbers below come from that project.

Editor UX: familiarity vs fit-for-purpose

WordPress's editor is genuinely good for people who learned content editing on WordPress. Gutenberg's block library is wide, the media library is tactile, and non-technical editors can add pages without any developer help. That's a real advantage. When I've handed off WordPress sites to marketing teams who already know the platform, training time is near zero.

Sanity Studio is a different experience. The editing surface is structured rather than visual — you fill in typed fields rather than assembling blocks freehand. Editors who come from a publishing or ops background adapt quickly because it feels more like a form than a page canvas. Editors who came from Gutenberg needed about two weeks to stop reaching for the block inserter. The payoff is that the content model is explicit: a "hero" is always a hero, a "testimonial" always has a quote and an author reference, and GROQ queries stay predictable.

For the migration project, I ran both studios in parallel for three weeks. After go-live, none of the three editors asked to go back. The structured model reduced publishing errors — they'd previously broken layouts by pasting rich text with inline styles into heading fields.

Performance: the gap is real

On the old WordPress + WPGraphQL stack, the site averaged 2.8 s LCP on mobile (Lighthouse CI, median of 30 runs, same test pages). After migrating to Sanity + Next.js App Router with ISR, the same pages averaged 1.1 s LCP. TTFB dropped from 480 ms to 60 ms once pages were edge-cached on Vercel.

WordPress headless is not inherently slow — WPGraphQL is capable, and a well-cached WordPress API can perform well. But WordPress still loads PHP, initialises a plugin stack, and hits MySQL on cache misses. Sanity's CDN-backed Content Delivery API returns JSON from an edge node. The ceiling is higher with Sanity once you invest in the query layer.

CLS was the other win. WordPress's media library stores dimensions inconsistently — plugins resize images and lose the originals. Pre-calculating crop dimensions from Sanity's asset metadata let me pass explicit width and height to next/image on every image, eliminating layout shift entirely on image-heavy pages. That work is described in detail in a separate post; the short version is that Sanity stores the original dimensions in the asset document and you can project them at query time.

Developer experience

WordPress headless requires two distinct systems: the WordPress install (PHP, MySQL, plugins, theme files even if unused) and the front-end framework. You maintain both. WPGraphQL adds a third dependency. Schema changes require ACF or a custom plugin, which means PHP. TypeScript types for the API response are hand-written or generated from an introspection query that drifts the moment a plugin updates.

Sanity's developer experience is TypeScript-native end to end. Schemas are TypeScript objects. Sanity TypeGen generates types from those schemas, so your GROQ query results are typed at compile time. The Studio is a React app you extend with your own components. All of this lives in your repo — one deployment target per environment.

// sanity/schemas/post.ts
import { defineType, defineField } from 'sanity'
 
export const postSchema = defineType({
  name: 'post',
  title: 'Post',
  type: 'document',
  fields: [
    defineField({ name: 'title', type: 'string', validation: r => r.required() }),
    defineField({ name: 'slug', type: 'slug', options: { source: 'title' } }),
    defineField({ name: 'publishedAt', type: 'datetime' }),
    defineField({ name: 'body', type: 'array', of: [{ type: 'block' }] }),
  ],
})
// npx sanity typegen generate → PostDocument type available in queries

The friction point with Sanity is the content model itself. WordPress gives you posts and pages on day one with no schema design required. With Sanity you make decisions upfront — what document types do you need, how do references work, what goes in a global settings document. That's an upfront cost of roughly 8–12 hours on a medium-complexity site, but it pays back quickly in query predictability.

Plugin ecosystem: WordPress wins, with caveats

WordPress has ~60,000 plugins. Sanity has an ecosystem of official and community plugins (Mux video, Cloudinary, desk tools, internationalization) but it's much smaller. If you need a specific integration — a particular payment gateway, a niche LMS, a regional shipping provider — WordPress probably has a plugin. Sanity probably requires custom code.

The caveat is that WordPress plugins have a security and maintenance overhead that compounds. The migration project had 31 active plugins. Twelve of them existed to work around Gutenberg limitations or patch other plugins. Two had unfixed CVEs. Trimming to Sanity + a handful of focused API integrations reduced the attack surface substantially and removed a recurring maintenance cost the client had been absorbing as "normal".

Hosting cost and total cost of ownership

WordPress hosting with WP Engine (Growth plan) was running the client £65/month. Vercel Pro for the Next.js front-end added £18/month. Sanity's free tier covered their usage (under 10k API calls/day). Total after migration: £18/month ongoing, with Sanity free, versus £65/month before.

That's not always the outcome. High-traffic WordPress sites on shared hosting cost less than Vercel Pro. And the migration itself took 6 weeks of developer time — a one-time cost that only makes sense if you're planning to hold the site for 18+ months or if the WordPress maintenance overhead is already significant. I won't pretend Sanity is the cheaper option for a five-page brochure site that's been running on a £10/month shared host for three years.

When to stay on WordPress

WordPress headless makes sense when your team already runs WordPress at scale, when you have heavy WooCommerce dependencies, or when the editor team is large and deeply invested in Gutenberg. WordPress's user management, multisite, and comment/membership ecosystems are genuinely hard to replicate in a custom Sanity setup without third-party services.

WordPress also wins for projects with a tight timeline and a developer who knows the stack. A skilled WordPress developer can ship a new marketing site faster than a Sanity project if the Sanity content model needs to be designed from scratch.

When Sanity headless is the right call

Sanity earns its place when the content model is complex and needs to stay consistent across multiple front-ends (web, app, email), when the team wants TypeScript discipline across the CMS and the front-end, or when long-term maintenance cost matters more than setup speed. The performance ceiling is also meaningfully higher — not because Sanity's API is magic, but because the delivery layer is designed for edge caching from the start, whereas WordPress was designed for server rendering and has been adapted for headless use after the fact.

The migration numbers are real: 60% reduction in LCP, 87% reduction in TTFB on cached pages, and a hosting bill that dropped by more than half. That's a strong case — but it took six weeks to get there, and it would not have been worth it on a shorter-lived project.

Related posts

All posts →