Strapi vs Directus vs Payload: Self-Hosting a Headless CMS on a VPS (2026)

Strapi vs Directus vs Payload: Self-Hosting a Headless CMS on a VPS (2026)

By Fanny Engriana Β· Β· 8 min read Β· 9 views

Every few months a client asks me the same question: "We're tired of WordPress β€” what headless CMS should we self-host?" In the last year alone I've stood up content backends for three of our 50+ projects at Warung Digital Teknologi, and the shortlist always comes down to the same three names: Strapi, Directus, and Payload. The marketing pages all promise the same thing. The VPS bill, the 3 a.m. out-of-memory restart, and the migration headache two years later do not.

This is the comparison I wish existed when I picked the wrong one the first time. I'll cover the architecture differences that actually matter, the real RAM each one eats in production, what they cost when you self-host on a $7–20/month VPS, and which I'd put on which project today. No "it depends" cop-outs β€” I'll tell you what I'd choose.

The 30-second answer

If you only read one paragraph: pick Payload if your frontend is already Next.js and your team lives in TypeScript. Pick Directus if you have an existing SQL database that is the source of truth and non-developers need to edit data. Pick Strapi if you want the largest plugin ecosystem and the most hiring-pool familiarity, and you can spare the RAM. Everything below is the evidence for why those three sentences are true.

Architecture: code-first, database-first, framework-native

These three tools look similar in a feature grid but think about content in fundamentally different ways. That difference is the single biggest predictor of whether you'll be happy in year two.

Strapi β€” code-first, but config lives in files and the DB

Strapi (now at v5) is code-first: you define content types through its Content-Type Builder, which writes schema files to your repo. The admin panel is a React app it serves itself. The tradeoff I've seen in production is that Strapi owns its own database schema β€” it creates the tables, names the columns, and manages migrations. That is great until you need to point it at a database another application also writes to. You can't, cleanly. Strapi expects to be the owner.

Directus β€” database-first, the CMS wraps your tables

Directus inverts this. It is database-first: you point it at an existing PostgreSQL, MySQL, SQLite, MS SQL, or OracleDB schema and it generates an admin UI and a REST/GraphQL API on top of whatever tables are already there. When I integrated a content layer into a client's existing reporting database last year, Directus was the only one of the three that didn't demand we restructure anything β€” it read the foreign keys and built the relations for us. If SQL is already your source of truth, this is a category-of-one advantage.

Payload β€” framework-native to Next.js

Payload shipped 3.0 as a ground-up rewrite that installs into a Next.js app rather than running as a separate service. Your CMS admin and your frontend share one Node process, one deploy, one repo. For our projects already on Next.js β€” and most of our newer React work is β€” this collapses the "CMS server plus frontend server" architecture into a single deployable. Config is pure TypeScript, so your content schema is type-checked against your frontend code. That tight coupling is the whole point, and also the whole risk: Payload is a bet on Next.js specifically.

Developer comparing headless CMS configuration code on screen
Payload's config is plain TypeScript checked against your frontend; Strapi and Directus keep schema in their own layer.

The RAM reality β€” this is where VPS budgets die

Here is the number nobody puts on their landing page, and the one that decides your monthly bill. Across the projects where I've run all three on Hostinger VPS and Hetzner Cloud instances, the resting memory footprint is not close:

  • Strapi v5: feature-rich but memory-hungry. Budget 4 GB+ for a production instance. On a 2 GB box I watched it OOM-kill itself during a media-heavy import β€” the Node process plus the admin build plus Sharp image processing simply doesn't fit comfortably.
  • Directus: middle of the road, 2–4 GB depending on how many collections and how much concurrency. A single quiet project lives happily in 2 GB; add real editorial traffic and you want 4.
  • Payload 3.0: the leanest of the three β€” 2 GB handles most projects well because it piggybacks on the Next.js runtime you were already paying for.

Translate that to a VPS plan and the gap is stark. Strapi alone pushes you onto a 4 GB plan (roughly $12–16/month at Hetzner/Contabo tier). Payload fits on a 2 GB plan (~$5–8/month) and serves your frontend from the same box. Over a 3-year project life that single architectural choice is a few hundred dollars β€” not nothing, but the bigger cost is the 4 a.m. restart cron you'll write to babysit an undersized Strapi box. I've written that cron. Don't be me.

The right deployment shape for any of them

Whichever you choose, do not run the database and media on the same VPS disk as the CMS process. The shape I now use on every serious deployment is three components:

  1. A VPS for the CMS process β€” sized per the RAM table above.
  2. A managed Postgres (Supabase, Neon, or a managed DB add-on) so you are not the one babysitting WAL files and backups.
  3. S3-compatible object storage for media (Backblaze B2, Cloudflare R2, or any MinIO-compatible bucket) so uploads aren't trapped on a single disk and backups are trivial.

The first time I ran a Strapi instance with media on the local VPS disk, a routine snapshot-and-restore lost two weeks of editor uploads because the snapshot and the database backup were taken seconds apart but not atomically. Move media to S3 on day one. All three CMSes support an S3 storage adapter natively.

Self-hosted cost: the software is free, the hosting is not

All three are genuinely free and open source for self-hosting β€” there is no per-seat tax, no "contact sales" wall on the core. What you pay is hosting. Here's the realistic monthly total cost of ownership for a single production project, based on the plans I actually provision:

ComponentStrapi v5DirectusPayload 3.0
VPS (CMS process)4 GB ~$14/mo2–4 GB ~$8–14/mo2 GB ~$6/mo*
Managed Postgres~$5–10/mo~$5–10/mo~$5–10/mo
S3 media (50 GB)~$0.30/mo (B2/R2)~$0.30/mo~$0.30/mo
Frontend hostingseparateseparatesame box
Realistic TCO~$20–25/mo~$14–24/mo~$12–18/mo

*Payload's $6 VPS line item also hosts your Next.js frontend, which is why its column is lowest despite comparable database and storage costs.

For reference, the managed-cloud equivalents start at Payload Cloud's $35/mo Standard plan (512 MB RAM, 3 GB database) and climb to $199/mo for its Pro dedicated cluster. Strapi Cloud runs usage-based with a non-commercial free tier (2,500 API requests/month, cold starts). The self-hosted route on a VPS pays for itself the moment you run more than one project β€” which, running 7 aggregator sites myself, is the situation most agencies and serious operators are actually in.

Data center server racks hosting self-managed CMS infrastructure
Self-hosting on a VPS beats managed CMS cloud pricing the moment you run more than one project.

Developer experience and extensibility

Payload and Directus both let you build custom workflows in code with essentially no ceiling β€” hooks, custom endpoints, access-control functions, the lot. Strapi is more constrained here: its plugin system is broad but you bump into the framework's assumptions faster when you need something non-standard. The flip side is Strapi's ecosystem size β€” it has the most third-party plugins and, just as importantly, the largest hiring pool. When I need to hand a CMS to a client's in-house junior dev, "we use Strapi" gets nods; "we use Payload" gets blank looks, even though Payload is the nicer codebase.

On the editor side, Directus and Payload both ship granular roles and permissions, live preview, and publication workflows. Directus's data-explorer UI is the most comfortable I've handed to a non-technical content team β€” it reads like a spreadsheet that happens to be an API. Payload's admin is cleaner and more modern but assumes a developer set up the collections thoughtfully first.

i18n, AI, and the 2026 feature creep

All three now ship internationalization, and all three have bolted on some flavor of AI assist (content generation, alt-text suggestions, chat-with-your-content). Treat the AI features as a tiebreaker, not a deciding factor β€” they're thin wrappers over the same OpenAI-class APIs you could call yourself, and I've never seen one survive contact with a real editorial workflow as more than a novelty. If a vendor's pitch leans hard on AI, read it as a signal the fundamentals are commoditized.

Migration risk β€” the question to ask before you commit

The honest year-two question is: how hard is it to leave? Directus wins here by construction β€” your data lives in a plain SQL schema you defined, so worst case you drop Directus and keep the database. Strapi is the hardest to leave because it owns its schema and bakes its own conventions into the tables. Payload sits in between, but its tight Next.js coupling means leaving Payload often means rethinking your frontend too. I weigh this heavily now, having once spent a brutal sprint extracting content out of a CMS that did not want to let go.

What I'd actually choose, by scenario

  • Next.js frontend, TypeScript team, greenfield: Payload 3.0. One repo, one deploy, type-safe end to end, lowest VPS bill. This is my default for new React work now.
  • Existing SQL database is the source of truth: Directus, no contest. Nothing else respects your existing schema.
  • Non-technical editors, mixed frontend stack, need plugins and hireability: Strapi β€” provision the 4 GB box and don't fight the memory.
  • Tiny budget, single VPS, one project: Payload, because it shares the box with your frontend and fits in 2 GB.

FAQ

Can I run any of these on a $5 shared-hosting plan?

No. All three are Node services that need a persistent process and 2 GB+ of RAM. Shared hosting kills long-running Node processes. You need a VPS or a Node-friendly PaaS at minimum.

Do I really need a managed database, or can I run Postgres on the same VPS?

You can co-locate Postgres to save money on a hobby project, and on a 4 GB box it's fine. For anything a client depends on, a managed database removes the single most error-prone thing you'd otherwise babysit β€” backups, point-in-time recovery, and version upgrades. The $5–10/month is cheap insurance.

Which has the best performance under load?

Payload and Directus both serve API responses with less overhead than Strapi in my testing, largely because Strapi's middleware stack is heavier. But for a typical content site serving cached pages, the CMS is rarely the bottleneck β€” your reverse proxy and CDN config matter far more. Get caching right before you optimize the CMS.

Is SQLite enough for production?

For a low-write content site behind a CDN, SQLite (with a replication layer like Litestream) is genuinely viable and all three support it. For anything with concurrent editors or write-heavy collections, use Postgres.

Bottom line

There is no universal winner, but there is a clear winner for your situation, and it's usually obvious once you answer two questions: is your frontend Next.js, and do you already have a database that's the source of truth? Yes to the first β†’ Payload. Yes to the second β†’ Directus. Neither, but you need plugins and easy hiring β†’ Strapi with a 4 GB box. Size the VPS for the real RAM footprint, push media to S3 on day one, and use a managed database. Do those three things and any of the three will serve you well for years β€” the failures I've seen were never the CMS, they were undersized boxes and media trapped on a dying disk.

Found this helpful?

Subscribe to our newsletter for more in-depth reviews and comparisons delivered to your inbox.