Payload or Sanity, from a PHP developer's chair

If you come from Kirby, Craft or WordPress, the two headless CMSes people will point you at are Sanity and Payload. They look similar on the surface. Both are code-first: you describe your content types in TypeScript files and an admin form appears. Both store rich text as structured JSON rather than HTML. Both have drafts, live preview and a query API. Underneath, they are built on opposite ideas about where the application should live.

Where the pieces run

Sanity splits a site into three parts. The content store is a hosted service: your documents, your images, the API that serves them. The studio is the admin panel, a small React app that talks to that store from the browser. The public site is a third app, in my case Astro, that asks the store for the fields it needs and writes out static HTML. Nothing has to be running anywhere for the content to be served.

Payload is one application. Admin, API and database access are a single Node app, backed by Postgres or MongoDB, and since version 3 that app is a Next.js project with the admin mounted on a route inside it. In PHP terms, that is a lot closer to what you know: one codebase, one server, your own database. It is also a process that has to be running around the clock for anyone to log in.

What that means day to day

With Sanity you never think about backups, database upgrades or scaling, because you do not have a database. You think about seats and API quotas instead, and the free tier covers a client blog comfortably. Schema changes mean redeploying the studio, which is a folder of static files, and the site rebuilds itself from a webhook when something is published.

With Payload you own everything, including the ops. The data is in your Postgres. There are no seat limits and no per-project pricing, because the software is open source. In exchange you run Node in production, you patch it, and you are inside the Next.js upgrade cycle for the CMS itself, not just for the site. The version churn that makes JavaScript projects tiring applies to your admin panel too.

Editing and modelling

Defining fields feels the same in both. Sanity's query language, GROQ, is more expressive than Payload's REST and GraphQL endpoints, and Sanity's image CDN, which crops and resizes from URL parameters, is a genuine convenience that Payload leaves to you. Payload's admin is more conventional, with built-in authentication, granular access control and local file uploads, and it tends to be easier for a client to pick up on the first day. Sanity's studio is more customisable and has more AI tooling built in, some of it paid.

Which one

If what you miss from PHP is the feeling of one application you fully control, Payload gives you that back, at the price of more JavaScript to maintain rather than less. If what you want is a client site you can hand over and forget, with nothing to babysit, Sanity is the better fit. A static Astro build on a plain web server plus a hosted studio is close to zero maintenance, and the admin never goes down because your server did.

This blog runs on the Sanity side of that choice. Content in Sanity, four dependencies in the site, static files on a server I already had. Ask me again after the first client project.

Back to all blog posts