Headless CMS Comparison: SonicJS vs Payload, Strapi, Directus, Sanity & Contentful

These six are among the most popular headless CMSs β€” but they make very different trade-offs. SonicJS runs on Cloudflare Workers with a D1 (SQLite) database. Payload, Strapi, and Directus are mature, self-hostable Node.js platforms. Sanity and Contentful are hosted SaaS content platforms with deep enterprise features but no self-hosting and significant plan-gating. The table below is a full inventory of 125+ capabilities across 13 categories β€” meant as an honest reference, including the many places where the others are still ahead of SonicJS.

βœ“Built-inβœ—Not supportedPartialLimited / custom codePluginVia official pluginPaidPaid / enterprise tierRoadmapPlanned, not shipped

6 products compared β€” scroll the table sideways to see Sanity & Contentful β†’

CapabilitySonicJSPayloadStrapiDirectusSanityContentful
Architecture & Runtime
RuntimeCloudflare WorkersNode.jsNode.jsNode.jsHosted SaaSHosted SaaS
Deployment modelGlobal edgeSingle-regionSingle-regionSingle-regionManaged SaaSManaged SaaS
Edge / serverless runtimeβœ“PartialVercelβœ—βœ—PartialCDNPartialCDN
DatabaseD1 (SQLite)Postgres Β· MongoPostgres Β· MySQLPostgres Β· +5Content LakeProprietary
Data layer / ORMDrizzleDrizzle Β· MongooseKnexKnexGROQβ€”
Typical cold start0–5 ms100–300 ms500–2000 ms300–1000 msn/an/a
Global edge distributionβœ“βœ—βœ—βœ—βœ“βœ“
Built-in caching3-tierPartialManualPartialPluginPartialCacheAPI CDNAPI CDN
Auto-scalingβœ“PartialInfraPartialInfraPartialInfraβœ“βœ“
Self-hostable anywherePartialCF onlyβœ“βœ“βœ“βœ—βœ—
Docker supportβœ—βœ“βœ“βœ“βœ—βœ—
Official managed cloudβœ—PaidPausedPaidPaidβœ“βœ“
Pricing & Licensing
LicenseMITMITMIT (+ EE)MSCLMIT / SaaSProprietary
Free to self-hostβœ“βœ“βœ“Partial<$5M revβœ—βœ—
Free cloud tierPartialCF free tierβœ—βœ—βœ—βœ“βœ“
Paid cloud entry priceFree / ~$5$35+/mo$15+/mo$25+/mo$15/seat~$300/mo
Features behind paywallβœ—βœ—PaidSeveralPartialSomePaidSeveralPaidMany
Content Modeling
Collections / content typesβœ“βœ“βœ“βœ“βœ“βœ“
Single types / globalsPartialβœ“βœ“Partialβœ“Partial
Repeatable / array fieldsβœ“βœ“βœ“βœ“βœ“βœ“
Reusable component / group fieldsβœ“βœ“βœ“Partialβœ“Partial
Blocks / dynamic zonesβœ“βœ“βœ“Partialβœ“βœ“
One-to-one relationshipsPartialβœ“βœ“βœ“βœ“βœ“
One-to-many relationshipsβœ“βœ“βœ“βœ“βœ“βœ“
Many-to-many relationshipsPartialβœ“βœ“βœ“βœ“βœ“
Polymorphic relationshipsPartialβœ“Partialβœ“βœ“βœ“
Conditional field logicβœ—βœ“βœ“βœ“βœ“βœ—
Field-level validationβœ“βœ“βœ“βœ“βœ“βœ“
Computed / virtual fieldsβœ—PartialPartialPartialPartialβœ—
Rich text editorTinyMCELexicalCKEditorTinyMCEPortable TextRich Text
Markdown fieldβœ“Partialβœ“βœ“Pluginβœ“
JSON fieldβœ“βœ“βœ“βœ“Partialβœ“
Custom field typesPartialβœ“βœ“Pluginβœ“Plugin
UI / presentational fieldsβœ—βœ“Partialβœ“PartialPartial
Field-level localizationRoadmapβœ“βœ“βœ“Pluginβœ“
Built-in field types (approx.)~21~22~15~25~13~12
Content Management & Editorial
Draft & publishβœ“βœ“βœ“βœ“βœ“βœ“
Version history / revisionsβœ“βœ“Paidβœ“Partial3-day freeβœ“
Autosaveβœ“βœ“βœ—βœ—βœ“βœ“
Scheduled publishingβœ“βœ“PaidPartialFlowsPaidPaid
Live previewβœ“βœ“Paidβœ“βœ“Partial
Editorial workflow / review stagesβœ“PartialPaidPartialPartialPaid
Bulk edit / deleteβœ“βœ“βœ“βœ“Partialβœ“
Document duplicationβœ“βœ“βœ“βœ“βœ“βœ“
Soft delete / trashβœ—βœ“βœ—PartialPartialPartial
Concurrent edit lockingβœ—βœ“PartialPartialβœ“Partial
Editorial commentsβœ—βœ—βœ—βœ“PaidPaid
Real-time collaborationβœ—βœ—βœ—βœ—βœ“Partial
APIs & Integration
REST APIβœ“βœ“βœ“βœ“βœ“βœ“
GraphQL APIRoadmapβœ“Pluginβœ“βœ“βœ“
GraphQL subscriptionsβœ—βœ—βœ—βœ“βœ—βœ—
Realtime / WebSocketsRoadmapβœ—βœ—βœ“βœ“βœ—
Local / server-side APIβœ“βœ“βœ“βœ“βœ—βœ—
Webhooksβœ“PartialHooksβœ“βœ“βœ“βœ“
Filtering / sorting / paginationβœ“βœ“βœ“βœ“βœ“βœ“
Deep relationship populationPartialβœ“βœ“βœ“βœ“βœ“
Aggregation queriesβœ—Partialβœ—βœ“βœ“βœ—
Field selection / sparse fieldsetsβœ“βœ“βœ“βœ“βœ“βœ“
Custom endpointsβœ“βœ“βœ“PluginPartialPlugin
OpenAPI / Swagger specβœ“Pluginβœ“βœ“βœ—Partial
Authentication & Authorization
End-user / app authβœ“βœ“βœ“βœ“βœ—βœ—
JWT / token authβœ“βœ“βœ“βœ“βœ“βœ“
API keys / tokensβœ“βœ“βœ“βœ“βœ“βœ“
OAuth / social loginPluginPartialβœ“βœ“βœ“Partial
SSO / SAMLRoadmapPaidPaidβœ“PaidPaid
Magic linkPluginβœ—βœ—βœ—βœ“βœ—
OTP / 2FA / MFAPluginOTPPluginβœ—βœ“Partialβœ“
Role-based access controlβœ“βœ“PartialAdv = EEβœ“Partial2 freePaid
Collection-level permissionsβœ“βœ“βœ“βœ“PaidPaid
Field-level permissionsβœ“βœ“Paidβœ“PaidPaid
Document / row-level accessPartialβœ“Partialβœ“PaidPaid
Custom access-control functionsβœ—βœ“βœ“PartialPaidβœ—
Password resetβœ“βœ“βœ“βœ“βœ“βœ“
Media & Assets
Media libraryβœ“βœ“βœ“βœ“βœ“βœ“
Image resizing / transformsβœ“βœ“βœ“βœ“βœ“βœ“
Focal pointβœ—βœ“βœ“βœ“βœ“βœ“
Cloud storage adaptersR2βœ“Pluginβœ“βœ—βœ—
File metadataβœ“βœ“βœ“βœ“βœ“βœ“
Alt text / captionsβœ“βœ“βœ“βœ“PartialPartial
Folders / organizationβœ“βœ“βœ“βœ“PartialPartial
Image optimizationβœ“Partialβœ“βœ“βœ“βœ“
CDN integrationβœ“PartialPartialPartialβœ“βœ“
Internationalization
Content localization (i18n)Roadmapβœ“βœ“βœ“Pluginβœ“
Locale fallbacksRoadmapβœ“βœ—PartialPluginβœ“
Admin UI translationsβœ—βœ“βœ“βœ“βœ“Partial
RTL supportβœ—βœ“Partialβœ“Partialβœ“
Admin Panel & UI
Built-in admin UIHTMXReact / NextReactVueReact (Studio)Web app
Custom components / fieldsPartialβœ“βœ“Pluginβœ“Plugin
Customizable dashboardβœ“βœ“Partialβœ“βœ“Plugin
Custom admin views / routesβœ“βœ“βœ“Pluginβœ“Plugin
Theming / white-labelPartialβœ“PartialPartialPartialPaid
Dark modeβœ“βœ“βœ“βœ“βœ“βœ—
List view configurationβœ“βœ“βœ“βœ“βœ“βœ“
Conditional field displayβœ—βœ“βœ“βœ“βœ“βœ—
Extensibility & Automation
Plugin / extension systemβœ“βœ“βœ“βœ“βœ“βœ“
Lifecycle hooksβœ“βœ“βœ“βœ“PartialPartial
Middlewareβœ“Partialβœ“PartialPartialβœ—
Custom endpointsβœ“βœ“βœ“βœ“PartialPlugin
Cron / scheduled jobsPartialβœ“βœ“βœ“PartialPartial
Background jobs / queuesβœ—βœ“βœ—Partialβœ—βœ—
Email sendingβœ“βœ“Pluginβœ“βœ—βœ—
Visual automation builderβœ—βœ—βœ—βœ“βœ—Paid
Custom CLIβœ—PartialPartialPartialβœ“βœ“
Developer Experience
TypeScript supportβœ“βœ“βœ“βœ“βœ“βœ“
Schema as codeβœ“βœ“βœ“βœ“βœ“βœ“
Type generation from schemaPartialβœ“βœ“Partialβœ“Plugin
DB / content migrationsβœ“βœ“Partialβœ“βœ“βœ“
Data seedingβœ“PartialPartialPartialPartialPartial
CLI scaffoldingβœ“βœ“βœ“βœ“βœ“Partial
Official JS / TS SDKβœ—βœ“βœ“βœ“βœ“βœ“
API playground / docs UIβœ“Partialβœ“Partialβœ“βœ“
Security & Operations
Rate limitingβœ“PartialPartialβœ“βœ“βœ“
CSRF protectionβœ“βœ“PartialPartialβœ“Partial
CORS configβœ“βœ“βœ“βœ“βœ“βœ“
Audit logsβœ“PartialPaidβœ“PaidPaid
Field encryptionβœ—Partialβœ—βœ—βœ—βœ—
GDPR / data-export toolsPartialPartialPartialβœ“Partialβœ“
Bot protection (CAPTCHA)PluginTurnstileβœ—βœ—βœ—PartialPartial
Database transactionsβœ“βœ“βœ“βœ“βœ“βœ—
Multi-tenancyPartialPluginβœ—PartialPartialβœ“
Ecosystem & Maturity
First released201820212015201220172013
GitHub stars (approx.)~1.6k~43k~72k~36k~6.2kClosed
Official plugins / marketplace~25 bundled~10 officialMarketplaceMarketplaceMarketplaceMarketplace
Visual page builderβœ—Partialβœ—PartialPartialPaid
Built-in AI featuresβœ“βœ—Paidβœ—PartialPaid

Data last verified June 2026against each project’s official docs, GitHub, and pricing pages. Sanity and Contentful are hosted SaaS platforms, so β€œself-hostable” rows are No and several features are plan-gated. Corrections welcome via GitHub.

How to read this

The matrix isn't scored or weighted β€” pick the rows that matter for your project. A few things worth knowing as context:

Architecture is the real fork in the road

SonicJS compiles to Cloudflare Workers, so there's no server to keep warm β€” cold starts are effectively 0–5 ms and reads are served from the global edge. Payload, Strapi, and Directus run as Node.js processes you host in a single region β€” flexible on database choice and battle-tested, but cold starts and global latency depend on your infrastructure. Directus is database-first (it layers onto an existing SQL database). Sanity and Contentful sidestep hosting entirely: their content lives in a managed cloud delivered over a global CDN, so you never run a server β€” but you also can't self-host, and you're billed per seat/usage.

Feature maturity: the incumbents lead in many areas

This is the honest part. Compared to SonicJS, the older platforms ship a number of things SonicJS doesn't have yet or only partially supports β€” most notably GraphQL, real-time/WebSockets, internationalization, soft-delete/trash, conditional fields, an official SDK, SSO/SAML, and richer relationship modeling. Directus in particular is very deep (Flows automation, Insights dashboards, GraphQL subscriptions). Strapi and Directus also have far larger ecosystems and longer track records.

Where SonicJS is differentiated

Its edge-native runtime (sub-50ms global reads, near-zero cold starts), built-in three-tier caching, and the fact that everything ships in the open-source core with no paywalls. Note the trade-offs that come with the edge model: a single database engine (D1/SQLite) and Cloudflare-only hosting rather than run-anywhere Docker.

Pricing & feature gating

The self-hostable four are free to run (Directus requires a commercial license above $5M revenue). What's gated differs: Strapi puts version history, scheduled publishing, Live Preview, audit logs, advanced RBAC, and SSO behind paid Growth/Enterprise tiers; Payload is fully open-source (managed Cloud currently paused post-Figma-acquisition); Directus is source-available with a small-org grant; SonicJS has no feature paywalls and runs on Cloudflare's free tier. The two SaaS platforms gate more heavily: Sanity charges per seat and gates SSO, custom roles, comments, and content releases; Contentful has a usable free tier but reserves scheduled publishing, workflows, SSO, RBAC, and visual editing for plans starting around $300/mo.

Which should you pick?

Choose SonicJS if…

  • You want global edge performance with near-zero cold starts
  • You're already on (or moving to) Cloudflare
  • You want every feature free, with no per-seat or Enterprise gating
  • You value AI-agent-ready docs and a TypeScript-first codebase

Choose Payload / Strapi / Directus if…

  • You need GraphQL or real-time today
  • You depend on Postgres, MySQL, or MongoDB specifically
  • You want a large ecosystem and the control of self-hosting
  • Your traffic is regional and edge latency isn't a priority

Choose Sanity / Contentful if…

  • You'd rather not run any infrastructure at all
  • You need enterprise governance (audit, SSO, workflows) and have budget
  • Sanity: real-time multiplayer editing and GROQ matter to you
  • Contentful: you're standardizing a large org on a composable platform

Deep-dive comparisons

Want a closer look at a specific matchup? These guides go beyond the matrix with benchmarks, migration notes, and real-world developer feedback:

Frequently asked questions

Is SonicJS a good alternative to Strapi, Payload, or Directus?

SonicJS is a strong fit when you want an edge-native CMS on Cloudflare Workers with near-zero cold starts and no feature paywalls. The Node.js incumbents (Payload, Strapi, Directus) are more mature and still lead in areas like GraphQL, internationalization, real-time, and database flexibility β€” several of which are on the SonicJS roadmap. Pick based on whether edge performance or breadth of features matters more for your project.

Which headless CMS is the fastest?

Architecturally, SonicJS has the lowest cold start (0–5 ms) because it runs on Cloudflare Workers at the edge rather than a single-region Node.js server, so reads are served close to users worldwide. Payload, Strapi, and Directus performance depends on your hosting and caching setup. Real-world numbers vary by workload, so benchmark for your own use case.

Which of these headless CMSs are free and open source?

SonicJS, Payload, Strapi, and Directus are all self-hostable. SonicJS and Payload are MIT licensed. Strapi's Community edition is MIT but gates features like version history, scheduled publishing, Live Preview, audit logs, advanced RBAC, and SSO behind paid tiers. Directus uses the source-available MSCL license (free under $5M revenue). Sanity and Contentful are hosted SaaS β€” only Sanity's Studio editor is open source (MIT); their content backends are proprietary and can't be self-hosted, and Contentful is fully closed-source.

Does SonicJS support GraphQL and internationalization (i18n)?

Not yet β€” GraphQL and i18n are on the SonicJS roadmap. Today SonicJS ships a REST API with an OpenAPI spec. Payload, Strapi, and Directus all offer GraphQL and i18n today (Directus also offers GraphQL subscriptions and real-time over WebSockets).

Which headless CMS should I choose?

Choose SonicJS for global edge performance on Cloudflare with everything in the free core. Choose Payload for a Next.js-native, deeply typed developer experience. Choose Strapi for the largest plugin ecosystem and a mature admin. Choose Directus to layer a CMS and visual automation onto an existing SQL database. Choose Sanity for real-time multiplayer editing and the GROQ query language, or Contentful for an enterprise-grade composable platform you don't have to operate. The feature matrix above breaks down all six across 125+ capabilities.

Spot something out of date? Competitor pricing and features change fast. Open an issue or PR on GitHub and we'll correct it.

Was this page helpful?