
Directus CMS Guide: Database-First Headless CMS for Developers
Most headless CMSes want you to build your data model inside their system. Directus flips that, it wraps your existing SQL database and gives you instant REST and GraphQL APIs without touching your schema. With ~34.5k GitHub stars and adoption by companies like Tripadvisor, Adobe, and Mercedes-Benz, it's one of the most capable open-source options among the best headless CMS options in 2026.
| Attribute | Detail |
|---|---|
| Type | Open-source headless CMS |
| Architecture | Database-first (wraps existing SQL databases) |
| Databases | PostgreSQL, MySQL, MariaDB, SQLite, OracleDB, CockroachDB, MS-SQL |
| APIs | REST + GraphQL (simultaneous) |
| Self-Hosted | Free under $5M revenue (MIT license) |
| Cloud | From $25/month |
| AI Features | MCP server, AI Assistant (multi-provider) |
| Collaborative Editing | Native since v11.15 |
| Best For | Teams with existing databases, API-first projects |
| Not Ideal For | Visual page building, NoSQL, simple blogs |
| GitHub | ~34.5k stars |
| Latest Version | v11.16 (April 2026) |
What Is Directus CMS?
Directus is an open-source headless CMS that wraps any existing SQL database with instant REST and GraphQL APIs. Unlike Strapi or Payload, Directus doesn't create its own database schema, it mirrors yours. It supports 7 databases including PostgreSQL, MySQL, MariaDB, SQLite, OracleDB, CockroachDB, and MS-SQL, and is free for organizations under $5M revenue according to Directus's official documentation.
Think of it as a smart layer that sits on top of your database. You bring an existing PostgreSQL database with 50 tables, point Directus at it, and within minutes you've got a full admin UI, role-based access control, and both REST and GraphQL endpoints. No migration scripts. No data restructuring.
This is what "database-first" actually means in practice, and it's fundamentally different from the code-first approach used by Strapi (where you define content types that generate database tables) or the framework-embedded approach of Payload CMS (where the CMS lives inside your Next.js app).
Database-First Architecture Explained
When we first connected Directus to an existing PostgreSQL database for a client project, the thing that surprised us was how little setup was involved. Directus introspects your database schema, tables become "collections," columns become "fields", and builds its admin interface from what already exists.
This means your data is never locked into a proprietary format. If you decide to stop using Directus tomorrow, your database is still a standard SQL database. Try doing that with Contentful or Sanity, where your content lives on their servers in their format.
Directus also isn't just a CMS. The team positions it as a composable data platform, people use it for BaaS (Backend as a Service), internal admin panels, and custom dashboards. The CMS use case is the most popular, but the architecture supports much more.
Key Features of Directus
Directus provides dual REST and GraphQL APIs, granular role-based permissions, built-in Flows automation, a drag-and-drop Data Studio, digital asset management, and native i18n support for 50+ languages. Since v11.15, it includes collaborative editing and an AI Assistant as native features, not third-party plugins.
Here's what matters most if you're evaluating Directus for a project:
Dual REST and GraphQL APIs
Both APIs are available simultaneously from the same data, with zero configuration. You don't choose one or the other, you get both. Your mobile team can use REST while your web frontend uses GraphQL. The REST API follows a predictable pattern (/items/{collection}) and the GraphQL endpoint lives at /graphql.
Flows and Automation
Flows are Directus's event-driven automation system, built directly into the Data Studio UI. You can trigger workflows on CRUD events (item created, updated, deleted), schedules (cron-style), or webhooks. Operations include sending emails, making HTTP requests, running custom JavaScript, and transforming data.
For teams building with AI, Directus even has a native Model Context Protocol (MCP) guide server, but more on that in the v11 section.
Extensions and Customization
The extension system supports hooks (server-side event handlers), custom endpoints, UI panels, full modules, and operation nodes for Flows. Extensions are built with Vue.js for the frontend and plain Node.js for the backend. The v11.0 release restructured extensions from type-based folders to a cleaner bundled format.
Here's how Directus stacks up against the competition on features:
| Feature | Directus | Strapi | Payload | Sanity |
|---|---|---|---|---|
| Database Support | 7 SQL databases | PostgreSQL, SQLite | MongoDB, PostgreSQL | Hosted (proprietary) |
| API Type | REST + GraphQL | REST (GraphQL plugin) | Local API + REST + GraphQL | GROQ + GraphQL |
| Self-Hosted | Yes (free <$5M) | Yes (free) | Yes (free) | No |
| Visual Builder | Data Studio (data-focused) | Content-Type Builder | Live Preview | Sanity Studio |
| i18n | Native (50+ languages) | Plugin-based | Field-level | Document-level |
| Automation | Flows (built-in) | Lifecycle hooks | Hooks + Jobs | GROQ-powered webhooks |
| Pricing Model | Revenue-based ($5M threshold) | Seat-based | Free + Cloud | Usage-based |
What's New in Directus v11 (2025-2026)
Directus v11 introduced native MCP server support (v11.13), an AI Assistant supporting OpenAI, Anthropic, and Gemini (v11.14), collaborative editing with live presence indicators (v11.15), and global draft versions with role-based deployment permissions (v11.16). These are all built-in features, not community extensions.
This is where Directus has been moving fastest, and it's the section most competitors completely miss. Only one of the top six ranking guides covers any of this.
MCP Server and AI Assistant
The v11.13 release made Directus one of the first CMSes with a native MCP server. If you're using Claude, ChatGPT, or any MCP-compatible AI tool, it can manage your Directus content directly, reading collections, creating items, updating fields, all while respecting your RBAC permissions. If you're new to MCP, our Model Context Protocol (MCP) guide explains the protocol in detail.
The AI Assistant (v11.14) is separate from MCP, it's a built-in chat interface inside the Data Studio that supports OpenAI, Anthropic, Gemini, and even local models through Ollama. By v11.16, it became multimodal: you can upload images and PDFs directly into the AI chat for processing.
Collaborative Editing and Draft Versions
Collaborative editing shipped in v11.15 with live presence indicators (you can see who else is editing the same item) and field-level locking to prevent conflicts. The same release added a Vercel deployment module with role-based deploy permissions.
v11.16 took content staging further with global draft versions. Every versioned item automatically gets a draft copy. Editors can preview changes against the live version and promote drafts when ready. Role-based deployment permissions mean your content team can stage changes without accidentally pushing to production.
| Version | Date | Key Features |
|---|---|---|
| v11.0 | 2024 | New extension system, bundled format |
| v11.13 | Nov 2025 | Native MCP server support |
| v11.14 | Dec 2025 | AI Assistant (multi-provider), header interface |
| v11.15 | Feb 2026 | Collaborative editing GA, AI Assistant GA, Vercel deploys |
| v11.16 | Apr 2026 | Global draft versions, multimodal AI, role-based deployment |
Getting Started with Directus (Docker Setup)
You can run Directus locally with Docker in under 2 minutes. Create a docker-compose.yml file with the directus/directus image, set your database connection and admin credentials as environment variables, then run docker compose up. Directus starts at localhost:8055.
The Docker setup took us under 2 minutes from a cold start. Here's a complete docker-compose.yml with PostgreSQL included, not just the Directus container, but the full stack:
# docker-compose.yml
version: "3"
services:
database:
image: postgis/postgis:16-3.4-alpine
environment:
POSTGRES_USER: directus
POSTGRES_PASSWORD: directus
POSTGRES_DB: directus
volumes:
- directus_data:/var/lib/postgresql/data
directus:
image: directus/directus:11.16
ports:
- "8055:8055"
depends_on:
- database
environment:
KEY: "your-random-key-here"
SECRET: "your-random-secret-here"
ADMIN_EMAIL: "[email protected]"
ADMIN_PASSWORD: "change-me-please"
DB_CLIENT: "pg"
DB_HOST: "database"
DB_PORT: "5432"
DB_DATABASE: "directus"
DB_USER: "directus"
DB_PASSWORD: "directus"
volumes:
- directus_uploads:/directus/uploads
volumes:
directus_data:
directus_uploads:Run it:
docker compose up -dOpen http://localhost:8055, log in with the admin credentials you set, and you're in the Data Studio. From here you can create collections (tables), define fields (columns), and start managing content immediately. The KEY and SECRET environment variables are used for JWT token generation, use random strings in production, not the placeholders above.
Querying Data with the Directus SDK
The Directus JavaScript SDK provides type-safe access to your data through both REST and GraphQL. Install @directus/sdk, create a client with createDirectus(), and use readItems() to fetch collections with filtering, sorting, and field selection built in.
The SDK's composable pattern felt intuitive after working with libraries like Supabase's client. You start with a base client and add capabilities by composing functions:
// lib/directus.ts
import { createDirectus, rest, readItems, createItem } from '@directus/sdk';
const client = createDirectus('http://localhost:8055').with(rest());
// Fetch published articles with specific fields
const articles = await client.request(
readItems('articles', {
fields: ['id', 'title', 'slug', 'content', 'author.name'],
filter: {
status: { _eq: 'published' }
},
sort: ['-date_published'],
limit: 10
})
);Creating items follows the same pattern:
// Create a new article
const newArticle = await client.request(
createItem('articles', {
title: 'My New Post',
slug: 'my-new-post',
content: '<p>Hello from Directus.</p>',
status: 'draft'
})
);For authentication, you choose between staticToken() (for server-to-server communication) and authentication() (for user-facing apps with login flows):
import { createDirectus, rest, staticToken } from '@directus/sdk';
// Server-side with static token
const client = createDirectus('http://localhost:8055')
.with(staticToken('your-api-token'))
.with(rest());REST API Examples
Every SDK method has an equivalent REST endpoint. If you prefer working with curl or fetch directly:
# Fetch published articles
curl "http://localhost:8055/items/articles?filter[status][_eq]=published&sort=-date_published&limit=10&fields=id,title,slug"
# Create a new item
curl -X POST "http://localhost:8055/items/articles" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"title": "My Post", "status": "draft"}'GraphQL Queries
The same data is available through GraphQL at /graphql:
query {
articles(
filter: { status: { _eq: "published" } }
sort: ["-date_published"]
limit: 10
) {
id
title
slug
content
author {
name
}
}
}You don't need to configure or enable GraphQL separately, it's always available alongside REST.
Directus with Next.js (Framework Integration)
Connecting Directus to Next.js takes three steps: install @directus/sdk, create a lib/directus.ts client, and fetch data in your Server Components using readItems(). Directus returns raw JSON, so you have full control over rendering with no vendor-specific components.
This is the cleanest part of working with Directus. There's no special framework adapter, no Directus-specific React components, no build plugin. It's just data fetching. If you've worked with any REST API in Next.js, you already know how this works. For context on framework choices, see our Next.js vs Remix comparison.
First, create the shared client (this is the same file from the SDK section, but configured for your deployed instance):
// lib/directus.ts
import { createDirectus, rest, staticToken, readItems } from '@directus/sdk';
const directus = createDirectus(process.env.DIRECTUS_URL!)
.with(staticToken(process.env.DIRECTUS_TOKEN!))
.with(rest());
export default directus;
export { readItems };Then use it in a Server Component, no useEffect, no loading states, just async/await:
// app/blog/page.tsx
import directus, { readItems } from '@/lib/directus';
export default async function BlogPage() {
const posts = await directus.request(
readItems('posts', {
fields: ['id', 'title', 'slug', 'excerpt', 'date_published'],
filter: { status: { _eq: 'published' } },
sort: ['-date_published'],
})
);
return (
<main>
<h1>Blog</h1>
{posts.map((post) => (
<article key={post.id}>
<h2><a href={`/blog/${post.slug}`}>{post.title}</a></h2>
<p>{post.excerpt}</p>
<time>{post.date_published}</time>
</article>
))}
</main>
);
}That's it. No vendor lock-in. The same approach works with Astro, Nuxt, SvelteKit, or any framework that can make HTTP requests. Directus's official docs include framework-specific guides for Astro and Nuxt if you want those, but the pattern is identical: create client, call readItems(), render.
Directus CMS Pricing and Licensing (2026)
Directus is free to self-host under MIT license for organizations with less than $5M in annual revenue or funding. Above $5M, a commercial license is required for production use. Directus Cloud starts at $25/month (Starter) with Professional plans from $49-$499/month, according to their pricing page.
The $5M Revenue Threshold
This is the single most important business fact about Directus, and most guides either bury it or skip it entirely. Here's how it works:
- Under $5M annual revenue or total funding: Free forever. MIT license. Self-host anywhere. No feature restrictions.
- Over $5M in production: You need a commercial license. Contact Directus sales for pricing.
- Development and testing: Always free, regardless of company size. The threshold only applies to production deployments.
The $5M number includes venture funding, not just revenue. So a seed-stage startup with $6M in funding technically falls above the threshold. In practice, Directus hasn't been aggressive about enforcement for early-stage companies, but you should factor this into your planning.
Cloud Plans
If you don't want to manage infrastructure, Directus Cloud handles hosting, backups, and updates:
- Starter: $25/month, good for small projects, personal sites
- Professional: $49-$499/month, scales with storage, bandwidth, and asset transformations
- Enterprise: Custom pricing, SLA, dedicated infrastructure, priority support
No per-seat licensing. Your entire team uses the same plan. Compare that to Contentful, which charges per user (see our Contentful pricing breakdown), or Sanity, which charges based on API usage and dataset bandwidth.
| CMS | Free Tier | Paid Starts At | Pricing Model | Self-Hosted |
|---|---|---|---|---|
| Directus | Yes (<$5M revenue) | $25/month (Cloud) | Revenue-based | Yes |
| Strapi | Yes (fully open-source) | $29/month (Cloud) | Seat-based | Yes |
| Payload | Yes (fully open-source) | Cloud (beta) | TBD | Yes |
| Contentful | Yes (limited) | $300/month | Seat + usage | No |
| Sanity | Yes (limited) | $15/month | Usage-based | No |
Directus vs Strapi vs Payload: How They Compare
Directus wraps existing databases without migration, Strapi generates its own schema from content types, and Payload embeds directly into your Next.js app. Directus supports 7 databases, Strapi supports 2, and Payload supports 2. All three are open-source, but their philosophies are quite different.
Having built projects with both Strapi and Directus, the biggest difference is how they think about your database. With Strapi, you define content types in the admin UI or code, and Strapi creates and manages the database tables for you. With Directus, the database is the source of truth, Directus reads it and adapts.
| Feature | Directus | Strapi | Payload |
|---|---|---|---|
| Architecture | Database-first (wraps existing DB) | Code-first (generates DB from models) | Framework-embedded (lives in Next.js) |
| Databases | PostgreSQL, MySQL, MariaDB, SQLite, OracleDB, CockroachDB, MS-SQL | PostgreSQL, SQLite | MongoDB, PostgreSQL |
| APIs | REST + GraphQL (both native) | REST (GraphQL via plugin) | Local API + REST + GraphQL |
| Admin UI | Data Studio (Vue.js) | Content Manager (React) | Admin Panel (React, embedded) |
| GitHub Stars | ~34.5k | ~68k | ~33k |
| Cloud Hosting | Directus Cloud ($25/month+) | Strapi Cloud ($29/month+) | Payload Cloud (beta) |
When to choose Directus: You have an existing database, you want dual REST+GraphQL out of the box, or you need to support less common databases like OracleDB or CockroachDB.
When to choose Strapi: You want the largest ecosystem and community, you prefer defining content types through a UI, or you're starting from scratch without an existing database. Read our full Strapi guide for details.
When to choose Payload: You want the CMS embedded directly in your Next.js application, you prefer TypeScript-first configuration, or you need a Local API that skips HTTP entirely. See our Payload CMS deep-dive for the full picture.
When NOT to Use Directus
Directus isn't the right choice if you need a visual page builder, a tightly integrated Next.js framework, or a NoSQL backend. It also adds overhead for simple projects where a flat-file CMS or WordPress would suffice.
We've seen teams choose Directus when they shouldn't have, and the pattern is usually one of these:
- You need a visual page builder. Directus's Data Studio is excellent for structured data management, but it's not a drag-and-drop site builder. If visual editing is your priority, look at Storyblok, see our Storyblok guide for how that compares.
- You're committed to NoSQL. Directus is SQL-only by design. If your data lives in MongoDB, Payload CMS is the natural fit.
- Your project is a simple blog. Spinning up Docker, PostgreSQL, and Directus for a personal blog is serious overkill. WordPress, Astro with markdown files, or even Ghost will get you publishing in a fraction of the time.
- You want CMS-in-framework. If you want your CMS to live inside your Next.js codebase as a first-class citizen, Payload does this natively. Directus is always a separate service.
- You're a large organization. If your company exceeds the $5M revenue threshold, you'll need a commercial license for production. Factor that cost against fully open-source alternatives like Strapi or Payload, where self-hosting is free regardless of revenue.
None of these are flaws, they're design decisions. Directus is a data platform, not a website builder. Knowing the difference saves you months of frustration.
FAQ
What is Directus CMS?
Directus is an open-source headless CMS that wraps any existing SQL database with instant REST and GraphQL APIs. It supports PostgreSQL, MySQL, MariaDB, SQLite, OracleDB, CockroachDB, and MS-SQL. Unlike traditional CMSes, Directus doesn't create its own schema, it reads and mirrors your existing database structure automatically.
Is Directus really free?
Directus is free to self-host under an MIT license for organizations with less than $5M in annual revenue or total funding. Above that threshold, you need a commercial license for production use. Development and testing environments are always free. Directus Cloud, their managed hosting, starts at $25 per month.
How is Directus different from Strapi?
Directus is database-first, it wraps your existing SQL database without modifying the schema. Strapi is code-first, you define content types and Strapi generates database tables. Directus supports 7 databases while Strapi supports 2. Both offer REST APIs, but Directus includes native GraphQL while Strapi requires a plugin.
What databases does Directus support?
Directus supports seven SQL databases: PostgreSQL, MySQL, MariaDB, SQLite, OracleDB, CockroachDB, and MS-SQL. It connects to your existing database and introspects the schema automatically. This multi-database support is unique among headless CMSes, most competitors support only one or two database engines.
Can Directus replace WordPress?
Directus can replace WordPress for content management, especially for headless or API-driven projects. However, Directus has no built-in frontend, themes, or page builder. You'll need to build your own frontend with a framework like Next.js or Astro. For simple blogs or sites needing visual editing, WordPress remains more practical.
Does Directus have a visual editor?
Directus includes a Data Studio, a powerful admin UI for managing structured data, building dashboards, and configuring permissions. However, it does not have a visual page builder or WYSIWYG site editor like Storyblok or WordPress. Directus is designed for data management, not drag-and-drop page composition.
Is Directus good for e-commerce?
Directus works well as a Product Information Management system, you can model product catalogs, manage attributes, and serve data via APIs. However, it's not an e-commerce platform. You won't get a shopping cart, checkout flow, or payment processing. Pair it with Shopify, Saleor, or Medusa for the transactional layer.
Can I use Directus with Next.js?
Yes. Install the @directus/sdk package, create a client pointing to your Directus instance, and fetch data in Server Components using readItems(). Directus returns plain JSON, so there are no vendor-specific React components required. The same approach works with any JavaScript framework including Astro, Nuxt, and SvelteKit.
Does Directus support collaborative editing?
Yes, since version 11.15 (February 2026). Directus has native collaborative editing with live presence indicators showing who's editing what, and field-level locking to prevent conflicts. This is a built-in feature, not a plugin. Combined with global draft versions in v11.16, teams can stage and preview changes before publishing.
What is the Directus MCP server?
Directus introduced a native Model Context Protocol server in v11.13 (November 2025). MCP allows AI tools like Claude and ChatGPT to interact with your Directus content directly, reading, creating, and updating items through natural language. The MCP server respects your existing RBAC permissions, so AI access follows the same rules as human users.