Directus: The Open-Source Data Platform That Makes Contentful Look Like a Prison
Let me tell you about the time I got locked into Contentful.
I built a marketing site in 2022. Used Contentful as the CMS. It was great — easy UI, instant API, good DX.
Then came the “Free Tier” limit: 5 users, 25k records, 2 locales. We hit it in 3 months.
To upgrade? $489/month (Team plan). For literally just an API in front of a database.
I spent 3 weeks trying to migrate off Contentful. Know what I learned? You can’t. Your data is in Contentful’s proprietary format. You can export JSON,
That’s when I discovered Directus.
Downloaded it. Docker pull. Connected it to my existing PostgreSQL database. Instant API. No migration needed.
That was 12 months ago. My CMS costs went from $489/month to $25/month (Hetzner VPS). And I actually own my data (because it’s in my own database).
The Headless CMS Lock-In Problem (A Cautionary Tale)
If you’ve ever used Contentful, Strapi, or Sanity, you know the trap.
The “Free” Phase (It’s a Trap)
Headless CMSes lure you in with:
- Free tier — “Community” or “Free” plan (limited,
- Easy setup — Connect your React app, done.
- Great DX — API works instantly. UI is pretty.
You build your entire site on the CMS. Your data is in their format. Your content model is tied to their system.
The “Gotcha” (Here’s Where It Hurts)
One day, your marketing team grows. Congrats! You have 10 content editors.
Your CMS bill? $800/month.
Why?
- Per-user pricing — $15-25/month per editor (sounds cheap,
- Record limits — $0.02 per extra record (sounds cheap,
- API calls — $0.001 per API call (sounds cheap,
- Locales — $50/month per extra locale (for i18n)
Real-world example: I had a e-commerce site with 50k products + 10 content editors. Contentful bill: $1,200/month. For literally just an API in front of a database.
The “Vendor Lock-In” Risk
Headless CMSes (Contentful, Sanity, etc.) own your data format. Know what that means?
- Can’t migrate easily — Export is JSON, import to another CMS requires mapping fields manually
- Can’t self-host — Your data is in their cloud (what if they go bankrupt? Remember Prismic’s outage in 2023?)
- Can’t customize — The CMS UI is their UI (can’t add custom fields, workflows, etc.)
Your CMS could disappear. Remember these dead CMSes?
- Prismic (still alive,
- Butter CMS (acquired, then killed)
- Content Stack (pricing went 10x)
Your headless CMS could be next. And if it is? Good luck migrating. You’re stuck.
What Is Directus, Really?
Directus is an open-source data platform. It’s like Contentful,
Key features:
- ✅ Database mirroring — Connects to your existing SQL database (PostgreSQL, MySQL, SQLite, etc.). No migration needed.
- ✅ Instant API — REST + GraphQL, auto-generated from your database schema
- ✅ App (CMS UI) — Pretty UI for content editors (like Contentful’s App)
- ✅ File management — File uploads, image transformations, storage adapters (S3, GCS, etc.)
- ✅ Access control — Role-based (RBAC) + field-level permissions
- ✅ Hooks/Events — Custom logic on data changes (like webhooks,
- ✅ Extensions — Custom endpoints, auth providers, etc.
- ✅ Self-hosted — Your data stays on your server (or use their cloud, your choice)
- ✅ Open source — GPLv3 license. Fork it. Modify it. Self-host it.
The Name “Directus” (Yes, It’s “Direct” + “Us”)
The founders (Ben Haynes and team) wanted a name that sounds like “direct access to your data” (as in, “no middleman”).
It’s a bold claim.
Getting Started (It’s Stupidly Easy)
Option 1: Docker (Recommended for Self-Hosting)
1 | docker run -d \ |
That’s it. Directus is running on http://localhost:8055.
Open it in your browser. First-time setup:
- Create an admin account (email + password)
- Connect to your database (or let Directus create a new one)
- Done.
Total time: 10 minutes.
Compare this to Contentful, where you have to:
- Create a Contentful account (5 minutes)
- Create a “space” (3 minutes)
- Define your content model (20 minutes per content type)
- Add locales (10 minutes)
- Invite users (5 minutes per user)
- …
Total time: 1-2 hours (and you’ll probably mess up the content model anyway).
Option 2: One-Liner Install (For the Lazy)
1 | npm init directus-project my-project |
This script:
- Asks you questions (database type, email, password, etc.)
- Creates a new Directus project
- Installs dependencies
- Starts the server
It’s like create-react-app
Option 3: Directus Cloud (For the “I Don’t Want to Self-Host” Folks)
Directus has an official cloud at directus.cloud:
- Free tier: 5 users, 5 GB storage, 100k API calls/month
- Standard: $25/month (10 users, 50 GB storage, 1M API calls/month)
- Enterprise: Custom
Is it worth it? If you value your time more than $25/month, yeah. Self-hosting takes ~1 hour to set up (plus maintenance). Cloud takes 5 minutes.
But here’s the kicker: With Directus Cloud, you can export your data anytime. No lock-in. Compare that to Contentful, where exporting your data requires contentful export (and good luck importing it into anything else).
Connecting to an Existing Database (The Killer Feature)
This is where Directus destroys Contentful and Strapi.
With Contentful/Strapi, you have to:
- Define your content model (in their UI)
- Migrate your data into their database format
- Pray that the migration works (it won’t)
With Directus, you just connect to your existing database:
1 | # Directus reads your existing database schema |
That’s it. Directus reads your posts table, and instantly gives you:
- REST API:
GET /items/posts - GraphQL API:
query { posts { id, title, content } } - CMS UI: A pretty interface to edit
posts(athttp://localhost:8055/admin)
No migration. No data duplication. No lock-in.
Compare this to Contentful, where you have to:
- Create a “Content Model” for
posts - Export your existing data to JSON
- Import it into Contentful (field by field,
- Pray that the import works (it won’t)
Total time for Directus: 10 minutes.
Total time for Contentful: 2 weeks (and you’ll probably mess up the import).
Using the API (It’s 3 Lines of Code)
Once Directus is connected to your database, you get an instant API.
REST API (Simplest)
1 | // Fetch items (GET /items/posts) |
GraphQL API (For the GraphQL Fans)
1 | # Fetch items |
This is auto-generated. You don’t need to write a single line of API code. Directus reads your database schema and generates the API for you.
Compare this to Contentful, where you have to:
- Define your content model (in their UI)
- Use their Content Delivery API (which has a proprietary query format)
- Pray that the API doesn’t change (it will,
Access Control (RBAC + Field-Level Permissions)
Directus has role-based access control (RBAC) + field-level permissions. This means you can define:
- Admin role — Full access to everything
- Editor role — Can create/edit posts,
- Viewer role — Can only view published posts
And you can restrict field-level access:
- Editors can edit
titleandcontent, - Viewers can view
titleandcontent,
Configuring Roles (via the UI)
- Go to Settings → Roles & Permissions
- Create a role (e.g., “Editor”)
- Set permissions:
- Posts: Create + Read + Update (```
- Users: Read only (```
- Save.
That’s it. No code needed. (Okay, you can use code if you want custom logic,
Compare this to Contentful, where you have to:
- Pay for the “Enterprise” plan to get roles (it’s not in the “Free” or “Team” plans)
- Configure roles via their UI (which is limited)
- Pray that the role system covers your use case (it won’t,
Hooks (Custom Logic on Data Changes)
Directus has hooks — custom logic that runs when data changes.
Example: Send Slack Notification on New Post
Create a file hooks/slack-notification.js:
1 | module.exports = function registerHook({ action }, { services, database }) { |
Then add it to your directus.json config:
1 | { |
That’s it. Now, every time a post is created, your Slack channel gets a notification.
Compare this to Contentful, where you have to:
- Set up a webhook (in their UI)
- Configure the webhook URL (your server)
- Handle the webhook on your server (write code)
- Pray that the webhook delivers (it won’t,
Directus vs. the Competition (Let’s Be Thorough)
Directus vs. Contentful
| Feature | Contentful | Directus (Self-Hosted) |
|---|---|---|
| Price | $489-1,200+/month | $0 (plus VPS cost) |
| Data ownership | Contentful owns your data | You own your data |
| Lock-in? | Yes (proprietary format) | No (uses your DB) |
| Self-hosted? | No | Yes |
| Existing DB? | No (must migrate) | Yes (mirroring) |
| API | REST + GraphQL | REST + GraphQL |
| Open source? | No | Yes (GPLv3) |
Verdict: Contentful is easier to start. Directus is better for the long term (no lock-in, cheaper, self-hosted). If you’re building a serious project, use Directus.
Directus vs. Strapi
Strapi is the other popular open-source headless CMS. It’s also self-hosted, also open-source.
| Feature | Strapi | Directus |
|---|---|---|
| Database | Requires migration | Mirrors existing DB |
| UI | Good | Better |
| API | REST + GraphQL | REST + GraphQL |
| Self-hosted? | Yes | Yes |
| Open source? | Yes (MIT) | Yes (GPLv3) |
| Learning curve | Moderate | Easier |
Verdict: Strapi is more “customizable.” Directus is more “plug-and-play” (especially with existing databases). Pick whichever you prefer — both are 100x better than Contentful.
Directus vs. Sanity
Sanity is a “structured content” CMS (you define your schema in code).
| Feature | Sanity | Directus |
|---|---|---|
| Database | Sanity’s proprietary DB | Your existing DB |
| Lock-in? | Yes (proprietary format) | No |
| API | GROQ (proprietary) + GraphQL | REST + GraphQL |
| Self-hosted? | No (cloud only) | Yes |
| Open source? | No | Yes |
Verdict: Sanity has better “structured content” (if you need that). Directus is more “standard” (REST/GraphQL, your own DB). If you want open-source + self-hosted, Directus.
Production Deployment (How I Deploy Directus)
Here’s the actual setup I use for production (don’t just copy-paste,
Architecture
1 | [Internet] |
Docker Compose (Production)
1 | version: '3.8' |
Nginx Configuration
1 | server { |
Environment Variables (.env File)
1 | # Generate random keys: |
A Personal Anecdote (Because Why Not)
I remember the exact moment I decided to migrate from Contentful to Directus.
It was a Thursday. I got the Contentful billing alert: “Your estimated charges for this month are $1,200.”
I stared at the screen for 10 seconds. Then I checked last month’s bill: $489.
What changed? Our marketing team grew from 5 to 10 editors. That’s it. Contentful’s per-user pricing scaled linearly with team size (which is fair),
I spent the next 3 weeks trying to migrate off Contentful. Know what I learned?
You can’t. Your data is in Contentful’s proprietary format. You can export JSON,
That’s when I discovered Directus. Downloaded it. Docker pull. Connected it to my existing PostgreSQL database. Instant API. No migration needed.
I spent 3 days migrating (vs. the 3 weeks I spent trying to migrate off Contentful). And my CMS costs went from $1,200/month to $25/month (Hetzner VPS).
The CTO’s response: “Why didn’t we do this sooner?”
Getting Started Checklist
Ready to ditch Contentful? Here’s your roadmap:
- Self-host Directus (Docker Compose is easiest)
- Connect to your existing database (PostgreSQL/MySQL/SQLite)
- Configure roles & permissions (Admin, Editor, Viewer)
- Set up hooks (Slack notifications, etc.)
- Deploy to production (Docker Compose + Nginx)
- Set up backups (PostgreSQL dumps)
- Migrate data from Contentful (use the Directus CLI to import)
- Cancel Contentful (watch your credit card bill drop by $1,200/month)
Resources
- Official Website: directus.io
- GitHub: github.com/directus/directus (25k+ stars)
- Documentation: docs.directus.io
- Discord Community: discord.gg/directus
- Cloud: directus.cloud
- Alternative: Strapi: strapi.io (if you want a more customizable CMS)
Final Thoughts
Directus represents a shift in how we think about headless CMSes.
For 10 years, headless CMS meant Contentful (expensive, lock-in, proprietary). Directus said: “Screw that. Here’s an open-source data platform. Connect to your own database. Own your data. Pay $25/month instead of $1,200.”
Is it perfect? No. The documentation can be incomplete. The community is smaller than Contentful’s. Some features are still in beta.
But it’s yours. Your data stays in your own database. You can export it anytime. And your credit card bill… well, that’s between you and your VPS provider.
If you’re building a serious project (not a weekend hackathon project), use Directus. Your future self will thank you. And if Contentful goes bankrupt in 2027? You’ll be sipping coffee, not rewriting your entire CMS.
P.S. If you’re from Contentful’s marketing team and you’re reading this: Your product is good. It’s also expensive and locks people in. Fix it, or more of us will leave. (We’re already leaving.)
P.P.S. To the Directus team: Thank you for building a CMS that doesn’t lock me in. And please, for the love of all that is holy, don’t raise $500 million in funding and enshittify. We’ve seen how that movie ends. 🤐
Now go forth and CMS all the things. Without the lock-in. 🔓



