Is sanity the best CMS?
Sanity suits developer-led teams that want content as code, but it isn't the best CMS for everyone. Where it wins, falls short and costs.
Sanity is the best CMS for a fairly specific kind of team: developers who want content modelled in code, editors who need real-time collaboration, and a front end (often Next.js) that can live with a hosted content database. It isn't the best CMS in general, because no CMS is. If you need to self-host your data, want a blog with a newsletter and checkout already bolted on, or have one editor and forty Markdown files, something else will cost you less time and less money.
I'll go through Sanity first, then weigh it against Contentful, Payload, Strapi, Storyblok, a plain Git-and-Markdown setup, headless WordPress and VeloCMS (a product I work on, so I'll be blunt about where it loses).
Last verified: 2026-10-08. Prices and limits below were read from each vendor's own pages today and they change, so check the linked page before you commit a budget.
The short version
- Sanity is strongest when: your content model is complicated, several people edit at once, and you're happy to write GROQ and some React.
- Sanity is weakest when: you need the data store on your own servers, your editors want a drag-and-drop page builder out of the box, or your content is small and static.
- Money: a $0 Free plan and a $15-per-seat Growth plan, with quotas that matter more than the headline price (Sanity pricing).
- Lock-in: the Studio is open source and hostable anywhere, the data store is not (package README).
What is Sanity actually good at?
Sanity is built as two separate pieces, and the split explains almost everything good and bad about it.
The first piece is the Content Lake, a hosted, real-time document store. Sanity describes it as the database built for content, and it keeps references between documents consistent, supports conditional mutations and streams changes to anything listening (Content Lake). The second piece is Sanity Studio, a React application that you configure, extend and deploy yourself. The package README describes the Studio as an open-source single-page application with a customisation framework, the repository carries the MIT license, and the same README says Sanity hosts your content in a real-time, hosted data store called Content Lake (github.com/sanity-io/sanity, package README). So the editing tool is code in your repository, while the storage is somebody else's infrastructure.
Schemas live in your repo
You describe your content types in TypeScript or JavaScript, and the Studio builds its forms from that description. Here's a trimmed example of the kind of thing I mean, using the defineType and defineField helpers the schema docs recommend for editor autocomplete (schema docs):
import {defineType, defineField} from 'sanity'
export const post = 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: 'author', type: 'reference', to: [{type: 'author'}]}),
defineField({name: 'publishedAt', type: 'datetime'}),
],
})
The payoff is boring in the best way: a schema change is a pull request, reviewed and shipped with the feature that needs it. Compare that with a content model that lives only in a vendor dashboard, where keeping staging and production in step is a separate chore (some dashboard-first tools offer environments to help with that).
GROQ lets the front end ask for exactly what it needs
GROQ stands for Graph-Relational Object Queries, and it's Sanity's query language for filtering, joining and reshaping documents on the server (GROQ introduction). If you've never seen it, it reads like a JSON-flavoured filter followed by a projection:
*[_type == "post" && defined(slug.current)]
| order(publishedAt desc) [0...10] {
title,
"slug": slug.current,
"author": author->name,
"cover": coverImage.asset->url
}
The -> follows a reference, the curly braces pick fields, and the pipe orders and slices. Sanity's own cheat sheet shows the same building blocks (query cheat sheet). Fetching one post by slug is the same shape with a parameter, *[_type == "post" && slug.current == $slug][0], so a page can pull a post and its author in a single request.
Sanity does ship a GraphQL API too, generated with sanity graphql deploy. But the docs are lukewarm about it: Studio schemas are more flexible than GraphQL can represent, array fields can't be filtered yet, mutations aren't exposed, and the generated API doesn't change until you redeploy it. They recommend trying GROQ instead (GraphQL docs). If your team standardised on GraphQL tooling years ago, that's a real consideration, and a point for Payload rather than a bug.
Real-time editing that doesn't fight you
Sanity's Studio page claims several editors can work in one document with character-level sync, with no locking and no merge conflicts (Sanity Studio). That's a vendor claim, so take it as one, but the plumbing is documented: a listen endpoint streams events over Server-Sent Events for any document matching a GROQ query, so your own app can react to edits too (real-time updates).
For a newsroom or a marketing org where three people routinely touch the same landing page, this changes the day. For a solo blogger it's a nice demo and nothing more.
Visual editing and the Next.js story
This is where Sanity has the most to show a Next.js developer. The Presentation tool is a Studio plugin that renders your real front end inside an iframe and lets editors click on content to open the matching document (Presentation tool). To make that work in an App Router project you'll lean on next-sanity, which its README bills as the all-in-one Sanity toolkit for production-grade, content-editable Next.js applications, with GROQ querying, Draft Mode, a <VisualEditing /> component, time, tag and path revalidation, and an optional embedded Studio (github.com/sanity-io/next-sanity).
The setup has more moving parts than the pitch implies. According to the visual editing guide, you need Draft Mode, the defineLive helper with <SanityLive /> for real-time refreshes, and stega encoding, which hides invisible source-map data inside your strings so overlays know what to link to (visual editing guide):
import {createClient} from 'next-sanity'
export const client = createClient({
projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID!,
dataset: 'production',
apiVersion: '2026-05-21',
useCdn: true,
stega: {studioUrl: 'https://your-studio.example.com'},
})
I'd budget a day to get this feeling right, more if your components compare or transform strings (stega characters inside a string you're about to === against are a classic way to lose an afternoon). Once it works, editors get something that feels like a visual editor on a code-first backend.
An image pipeline you don't have to build
Every uploaded image gets a CDN URL you can transform with query parameters: w and h for size, fit for aspect handling, fm for format, q for quality, and focal-point cropping (image URLs). The @sanity/image-url helper builds those URLs for you. It isn't glamorous, but it saves you building a resizing service.
Where does Sanity fall short?
A few things, and they're worth saying plainly because they decide whether Sanity is right for you.
You can't self-host the data. Sanity's own README describes Content Lake as a hosted data store, and a reply on Sanity's community answers page says there is no way to run the data store on your own servers (that reply is labelled an "AI Update", so treat it as indicative rather than contractual; ask Sanity's sales team if it's a hard requirement) (package README, Sanity answers). The Studio can go anywhere, since it's a single-page application that runs in the browser and talks to Sanity's hosted APIs, and the deployment docs describe Sanity hosting and self-hosting, with a separate guide for embedding it in your own app (Studio deployment). But the content stays on Sanity's side. If your compliance team needs everything inside your own VPC, that's a no, full stop.
There's a learning curve. GROQ is its own language. Schema-as-code means a non-developer can't add a field on a whim. A Studio you customise is a Studio you maintain, with dependency upgrades like any other React app.
It doesn't build your pages. Sanity gives you structured content and an editor; the site is yours to write. That's a feature if you wanted that control and a tax if you wanted a blog by Friday. And the quotas are real, which brings us to money.
How much does Sanity cost once a team grows?
Here's the pricing page as it reads today (sanity.io/pricing).
Free plan:
- Price: $0
- Seats: 20, with 2 permission roles (Administrator and Viewer; there is no Editor role on Free)
- Datasets: 2, public only
- Documents: 10,000
- API CDN requests: 1 million a month
- API requests: 250,000 a month
- Bandwidth and asset storage: 100 GB each
- Webhooks: 2
- Draft review history: 3 days
- Overage behaviour: hard caps, no overages allowed; Sanity's plans-and-payments docs say that once a quota is reached, API and CDN requests fail with HTTP 402 until the month resets or you upgrade (plans and payments)
Growth plan:
- Price: $15 per seat per month, up to 50 seats, with 5 permission roles
- Datasets: 2, private or public (the pricing page sells up to 2 extra datasets as an add-on at $999 per dataset per month)
- Documents: 25,000, a hard cap unless you buy the $299-a-month increased-quota add-on, which lifts it to 50,000 and raises the request, bandwidth and asset quotas
- Included usage: the same 1 million CDN requests, 250,000 API requests and 100 GB of bandwidth and assets as Free
- Overages (pay-as-you-go for usage beyond the quotas): $1 per additional 250,000 CDN requests, $1 per additional 25,000 API requests, $0.30 per GB of bandwidth, $0.50 per GB of assets
- Extras: five permission roles including Editor, comments, task management, scheduled drafts, 4 webhooks, 90 days of draft review history
- Dedicated support: an optional $799-a-month add-on
Enterprise is custom, and it's where SSO, content releases and a full audit trail appear.
A few things jump out when you do the arithmetic. The Free plan is generous on seats (20) and stingy on documents (10,000); a catalogue-style site with variants, authors, tags and localised copies can burn through that quickly. Growth is priced per seat, so ten editors and developers on paid roles is $150 a month before usage, and it scales linearly. Interestingly, moving from Free to Growth barely changes your included API and bandwidth allowances. What you're buying is an Editor role and the collaboration features, a modestly higher document cap (25,000 against 10,000) and the ability to go over the request, bandwidth and asset quotas without the site going down. Documents stay capped either way unless you add the quota add-on.
That last point deserves a second look. A Free-plan project that gets a traffic spike hits a ceiling rather than a bill, which can be good (no surprise invoice) or terrible (content that fails to load in production because you forgot to upgrade). Decide which failure you prefer before launch day.
The per-dataset price is the other trap. Many teams like a production dataset and a staging one, and two is what both plans include. A third dataset, for a preview environment or a per-client sandbox, is the line item to check before you plan around it.
What about lock-in and portability?
It's less scary than it sounds, but it's not nothing. Your schemas are code in your own repository, which is the portable part. Your content can leave through the CLI: npx sanity@latest datasets export production production.tar.gz produces an archive with a data.ndjson file (one JSON document per line), an assets.json map and the downloaded image and file binaries, with flags to skip assets or drafts (exporting data).
What doesn't travel is everything built on top. Every GROQ query in your front end has to be rewritten against another system's API, image URLs point at Sanity's CDN until you re-host them, and references need a mapping step on the way into a relational database. None of this is a trap, only a migration project, so budget for one if you ever leave.
Is Sanity better than Contentful?
That depends on what you're optimising for, and I can't turn it into a measurement. Here is what Contentful's pricing page lists (Contentful pricing). The page sits behind a bot check that blocked my direct fetches, so I read a text rendering of it; check the live page before you budget.
The Free plan is $0 and includes 10 users, 2 roles, 2 locales, 100K API calls and 50 GB of CDN bandwidth a month, with hard usage caps instead of overages. The Lite plan is $300 a month with 20 users, 3 roles, 3 locales, 1M API calls and 100 GB of bandwidth, plus comments, task management, scheduled publishing and live collaboration. Lite can go past its limits and pay for the overage ($5 per extra million API calls, $0.15 per extra GB of bandwidth), and a larger Lite Space is a further $850 a month. Enterprise is custom.
Set that beside Sanity's \(15-per-seat Growth plan and the arithmetic meets at one size: twenty paid seats on Sanity come to \)300 a month, the same as Lite's flat fee for up to 20 users. With fewer paid seats Sanity's list price is lower (though the included quotas aren't like for like), and past 20 users Lite stops and you're into a custom Enterprise quote, while Growth runs to 50 seats. Both free plans are capped rather than metered.
The bigger difference is philosophical. Contentful offers a visual modeler for content types and serves content over its own APIs; Sanity defines the model in code and puts GROQ first. If your team likes governance, a polished editor and a vendor with enterprise plans, Contentful is a comfortable choice. If your team wants the content model in Git and editors who can co-edit live, Sanity is the more natural fit. Both are hosted services, so neither hands you the data store to run yourself.
Is Sanity better than Payload or Strapi?
Only if you're content with renting your database. Payload and Strapi are the two big names for people who want to own it.
Payload describes itself as an open-source, fullstack Next.js framework: you write a config, and you get an admin panel, REST and GraphQL APIs, authentication, access control and a straight-to-database Node.js API, backed by MongoDB or Postgres, with the repository under the MIT license (Payload docs, repository). Because it lives inside your Next.js app, there's one repo and one deploy. The catch is operations: you run it. Payload Cloud's page is now headlined "Payload has joined Figma" and says deployment of new Cloud projects is currently paused, existing projects keep running, and Payload remains a self-hosted, open-source project you can deploy anywhere you can run a Next.js app, so for now the hosted path means picking your own provider (Payload Cloud update).
Strapi is an open-source headless CMS with a Content-type Builder, an admin panel with built-in role-based access control and a REST API (GraphQL comes through an official plugin), and it supports SQLite, PostgreSQL, MySQL and MariaDB (Strapi docs, database docs, GraphQL docs, repository). If you'd rather not self-host, Strapi Cloud's monthly prices are Starter at $35 per project, Pro at $90 and Business at $450, with the quotas rising from 100K to 1M to 10M API requests a month, and I saw no free plan there (Strapi Cloud pricing). Its builder UI is friendlier to non-developers than Sanity's code-first approach, at the price of a less code-centric workflow.
My read: Sanity wins on real-time editing and visual tooling, Payload on code ownership and a single deploy, Strapi on familiarity and a conventional REST API. If "we must own the database" is on your requirements list, cross Sanity off before you start.
What about Storyblok?
Storyblok is the one to look at when the editors, not the developers, are the center of gravity. Its Visual Editor lets a person click a block in the preview to open it in the editing pane, or click a block in the editor to jump to it in the preview, driven by a bridge script that reloads the page on save and publish (Visual Editor docs).
The pricing page lists a Starter plan at no cost, described as a limited plan for testing and personal projects, with 1 seat and 100K API requests a month. Growth is $99 a month ($90.75 a month billed annually), with 5 seats and 1M requests; Growth Plus is \(349 a month with 15 seats and 4M requests (Storyblok pricing). The visual editor shows as available on all three, and new spaces get a 45-day trial of Growth Plus. Against Sanity, you trade flexibility in modelling and querying for an editing experience marketers pick up quickly, and you pay a plan fee with a set number of seats included (extra seats are listed at \)15 each, up to a per-plan maximum) instead of a pure per-seat price. If your site is mostly composed pages and campaigns rather than structured data, Storyblok may well be the better call.
Do you even need a CMS? Markdown in Git
For a developer blog, docs site or small marketing site, the honest competitor is no CMS at all. Astro's content collections give you Markdown, MDX or JSON files with a Zod schema, generated TypeScript types and getCollection() queries (Astro docs). Next.js supports local MDX through @next/mdx, though the guide notes it doesn't handle frontmatter by default, so you add a remark plugin or gray-matter (Next.js MDX guide).
You get zero monthly fees, full portability and a review workflow your developers already know. You also get the limits: every editor needs Git comfort or a separate editing layer, there's no real-time collaboration, and anything relational gets awkward. If your whole team can open a pull request, this beats Sanity on cost and simplicity. If your editors can't, you'll end up bolting on a CMS anyway.
What about headless WordPress?
WordPress ships a REST API that exposes posts, pages and taxonomies as JSON so you can build a completely separate front end (REST API handbook), and the free, open-source WPGraphQL plugin adds a GraphQL schema on top (WPGraphQL). The upside is familiarity: editors already know the dashboard. The downside is that you're maintaining a PHP application and its plugins purely as a content API, with a posts-and-fields data model rather than free-form documents. It's sensible when a team has existing WordPress content and editors who won't be retrained, and a heavier choice when you're starting fresh.
Where does VeloCMS fit?
VeloCMS is a different kind of product, and I'll say up front that it's a poor match for most of what makes Sanity attractive. It's a hosted, blog-first platform: you get a blog, newsletter, paid memberships, commerce, a visual page builder and 40 built-in themes under one login, rather than a content API you build a site on top of (velocms.org). Monthly prices on the pricing page are Pro at $9, Business at $29 and Agency at $69 (annual billing is cheaper), each starting with a 14-day free trial; there is no free plan, the trial is the only free option, and the page says a card is collected at signup with no charge until day 15 (pricing). The homepage lists API access and webhooks on the Pro plan and says posts, members, media and settings export as JSON, CSV or Markdown.
Its honest weaknesses: it's young and its ecosystem is small next to Sanity, WordPress or Strapi. It isn't a schema-as-code content lake, so if you need arbitrary structured content shared across a site, an app and a kiosk, it's the wrong tool. And it's hosted-only, which means the same compliance limits as Sanity.
It's worth a look if you want to ship a publication with subscribers and a store and would rather configure than code.
When should you not use Sanity?
Skip it, or at least pause, when:
- Your data must sit on infrastructure you control.
- You have one or two editors and fewer than a hundred pages. Markdown in Git is simpler and free.
- Marketers need a page builder on day one without developer help. Storyblok, or a product with a native builder, gets you there faster.
- Your team doesn't write React or TypeScript. The Studio is a code project.
- Your content is large and flat, like a catalogue. Watch the document caps before you commit.
- You want predictable flat fees. Per-seat pricing plus usage overages is the opposite.
Who each option is best for
- Sanity: developer-led teams with complex content, several simultaneous editors and a Next.js (or other JavaScript) front end, who accept a hosted data store.
- Contentful: organisations that value an established vendor, a UI-driven content model and enterprise governance, and can absorb the jump from free to paid. Check current prices first.
- Payload: teams that want CMS and site in one TypeScript codebase, with the database under their control, and are happy to run it.
- Strapi: teams that want a conventional, self-hostable headless API with a builder UI for non-developers.
- Storyblok: marketing-driven sites where editors compose pages visually and a flat plan fee suits the budget.
- Markdown in Git: developer blogs, documentation and small sites where everyone can open a pull request.
- Headless WordPress: teams with existing WordPress content and editors, who want a new front end without retraining anyone.
- VeloCMS: solo creators and small publications who want blog, newsletter, memberships and a store in one hosted product, and who don't need a general-purpose content API or a mature ecosystem.
FAQ
Is Sanity free?
There's a $0 Free plan with 20 seats, 10,000 documents, 2 public datasets and hard monthly quotas for requests and bandwidth. Past that, Growth is $15 per seat per month with pay-as-you-go overages on requests, bandwidth and assets; documents stay capped unless you buy an add-on (Sanity pricing, plans and payments).
Can you self-host Sanity?
Partly. The Studio is open-source code (MIT) you can host yourself, but Content Lake is Sanity's hosted data store, and as far as I can find it can't be run on your own servers (Studio deployment, package README).
Is GROQ harder than GraphQL?
It's different rather than harder. GROQ has less ceremony for filtering and joining documents, but it's specific to Sanity, so the skill doesn't transfer. Sanity's own docs recommend GROQ over its generated GraphQL API (GraphQL docs).
Does Sanity work well with Next.js?
Yes. next-sanity covers GROQ fetching, Draft Mode, visual-editing overlays and revalidation, and the Presentation tool previews your real pages inside the Studio (next-sanity, Presentation tool). Expect some setup time.
Can I export my content from Sanity?
Yes. The CLI exports a dataset as an NDJSON file plus assets, and you can skip drafts or assets with flags (exporting data). Your queries and front-end code still need rewriting for whatever you move to.
Is Sanity better for a blog than a blogging platform?
Usually not, unless you want a custom front end. A blog-first product ships the pages, newsletter and memberships; Sanity ships the content backend and leaves the rest to you.
Sources
Last verified: 2026-10-08.
- Sanity pricing
- Sanity Content Lake
- Sanity GROQ introduction
- Sanity query cheat sheet
- Sanity schema types
- Sanity GraphQL docs
- Sanity real-time updates
- Sanity Studio
- Sanity Studio deployment
- Sanity Presentation tool
- Sanity visual editing with Next.js
- Sanity image URLs
- Sanity exporting data
- Sanity plans and payments
- Sanity answers on self-hosting
- Sanity repository
- Sanity package README
- next-sanity repository
- Contentful pricing
- Payload docs
- Payload Cloud update
- Payload repository
- Strapi docs
- Strapi Cloud pricing
- Strapi database docs
- Strapi GraphQL docs
- Strapi repository
- Storyblok pricing
- Storyblok Visual Editor
- Astro content collections
- Next.js MDX guide
- WordPress REST API handbook
- WPGraphQL
- VeloCMS
- VeloCMS pricing
