Payload CMS vs Directus en 2026 : Code-First vs Database-First
Payload CMS vs Directus en 2026 : Code-First vs Database-First
Si vous construisez un projet alimenté par un CMS headless en 2026 et que vous avez réduit vos options à Payload CMS et Directus, félicitations — vous avez bon goût. Les deux sont open-source, auto-hébergés et construits sur Node.js. Les deux ont des communautés actives et livrent des fonctionnalités rapidement. Mais ils représentent des philosophies fondamentalement différentes sur la façon dont votre schéma de contenu doit être créé, et cette différence se répercutera sur chaque décision que vous prendrez sur un projet.
J'ai livré des sites de production avec les deux au cours des deux dernières années. Voici ce que je pense vraiment, pas ce que les pages marketing disent.
Table des matières
- La division de la philosophie centrale
- Conception de schéma : Code-First vs Database-First
- TypeScript et expérience développeur
- Couche API et capacités de requête
- Panneau d'administration et édition de contenu
- Authentification et contrôle d'accès
- Performance et scalabilité
- Déploiement et hébergement
- Tarification et licences en 2026
- Quand choisir lequel
- FAQ

La division de la philosophie centrale
Laissez-moi énoncer cela clairement car c'est la chose la plus importante à comprendre :
Payload CMS est code-first. Vous définissez votre schéma dans des fichiers de configuration TypeScript. La base de données se conforme à votre code.
Directus est database-first. Vous pouvez le pointer sur une base de données existante et il introspect le schéma. L'interface d'administration se conforme à votre base de données.
Aucune approche n'est objectivement meilleure. Mais l'une sera dramatiquement meilleure pour votre projet, et se tromper à ce sujet signifie de la douleur plus tard.
Si vous êtes un développeur construisant un projet greenfield et que vous voulez que votre schéma CMS soit versionné aux côtés du code de votre application, Payload vous semblera comme chez vous. Si vous avez une base de données PostgreSQL existante avec 200 tables et que vous avez besoin d'une couche de gestion de contenu dessus, Directus vous économisera des semaines.
Conception de schéma : Code-First vs Database-First
L'approche Code-First de Payload
Dans Payload 3.x (la version majeure actuelle en 2026), vous définissez des collections dans des fichiers de configuration TypeScript :
// collections/Posts.ts
import type { CollectionConfig } from 'payload'
export const Posts: CollectionConfig = {
slug: 'posts',
admin: {
useAsTitle: 'title',
},
fields: [
{
name: 'title',
type: 'text',
required: true,
},
{
name: 'content',
type: 'richText',
},
{
name: 'author',
type: 'relationship',
relationTo: 'users',
},
{
name: 'publishedAt',
type: 'date',
},
{
name: 'status',
type: 'select',
options: [
{ label: 'Draft', value: 'draft' },
{ label: 'Published', value: 'published' },
],
defaultValue: 'draft',
},
],
}
Cette configuration est votre source de vérité. Quand Payload démarre, il génère automatiquement des migrations de base de données (Payload 3.x utilise Drizzle ORM sous le capot avec support PostgreSQL ou SQLite, et supporte toujours MongoDB). Votre schéma vit dans Git. Vous examinez les changements de schéma dans les PR. C'est le même flux que vous utiliseriez pour le code d'application, et c'est le but.
Payload génère également automatiquement des types TypeScript à partir de ces configurations. Donc quand vous interrogez posts dans votre frontend Next.js, vous obtenez une complète sécurité des types sans maintenir des définitions de types séparées.
L'approche Database-First de Directus
Directus prend la stance opposée. Vous pouvez :
- Pointer Directus sur une base de données existante et il lit le schéma
- Créer des collections via l'interface d'administration, qui génère des migrations SQL
- Utiliser le SDK Directus pour gérer le schéma de façon programmatique
// Créer une collection via Directus SDK
import { createDirectus, rest, createCollection } from '@directus/sdk'
const client = createDirectus('http://localhost:8055').with(rest())
await client.request(
createCollection({
collection: 'posts',
schema: {
name: 'posts',
},
meta: {
icon: 'article',
note: 'Blog posts',
},
})
)
Directus 11 (lancé fin 2025) a considérablement amélioré les outils de migration de schéma. Vous pouvez maintenant exporter et importer les snapshots de schéma sous forme de fichiers YAML, ce qui rend le contrôle de version plus pratique qu'avant :
# Exporter le schéma actuel
npx directus schema snapshot ./schema-snapshot.yaml
# Appliquer la différence de schéma à un autre environnement
npx directus schema apply ./schema-snapshot.yaml
Mais voici la vérité honnête : même avec ces améliorations, la gestion du schéma Directus ne semble pas aussi naturelle dans un flux Git que l'approche de Payload. Vous prenez des snapshots d'état plutôt que de déclarer l'intention.
Tableau de comparaison des schémas
| Aspect | Payload CMS | Directus |
|---|---|---|
| Source de vérité du schéma | Fichiers de configuration TypeScript | Base de données elle-même |
| Versioning du schéma | Flux Git natif | Snapshots YAML (amélioré en v11) |
| Support des bases de données existantes | Limité (chemin de migration) | Excellent (introspection) |
| Types générés automatiquement | Oui, à partir de la config | Oui, via SDK + CLI |
| Support des bases de données | PostgreSQL, SQLite, MongoDB | PostgreSQL, MySQL, MariaDB, SQLite, MS SQL, CockroachDB, OracleDB |
| ORM / couche de requête | Drizzle ORM (v3) | Moteur de requête personnalisé (basé sur Knex) |
| Génération de migrations | Automatique à partir des changements de config | Snapshots de différence de schéma |
TypeScript et expérience développeur
L'histoire TypeScript de Payload
Payload est TypeScript jusqu'aux os. Le projet entier est écrit en TypeScript, configuré en TypeScript et génère du TypeScript. Quand vous exécutez payload generate:types, vous obtenez des interfaces pour chaque collection :
// Auto-généré
export interface Post {
id: string
title: string
content?: RichTextContent
author?: string | User
publishedAt?: string
status?: 'draft' | 'published'
createdAt: string
updatedAt: string
}
Ces types circulent dans votre API locale, les réponses de l'API REST et les requêtes GraphQL. Dans Payload 3.x, puisqu'il s'exécute à l'intérieur de votre application Next.js, vous pouvez importer et utiliser ces types directement. Aucun SDK séparé nécessaire. Pas d'appels API pour le rendu côté serveur — vous interrogez directement la base de données :
// Dans un composant serveur Next.js
import { getPayload } from 'payload'
import config from '@payload-config'
export default async function BlogPage() {
const payload = await getPayload({ config })
const posts = await payload.find({
collection: 'posts',
where: {
status: { equals: 'published' },
},
})
// posts.docs est entièrement typé comme Post[]
return <PostList posts={posts.docs} />
}
C'est véritablement une excellente DX. Pas de saut réseau, types complets, et c'est juste... des fonctions.
L'histoire TypeScript de Directus
Directus a considérablement amélioré son support TypeScript. Le package @directus/sdk supporte les paramètres de type générique :
import { createDirectus, rest, readItems } from '@directus/sdk'
interface Schema {
posts: Post[]
users: User[]
}
interface Post {
id: number
title: string
content: string
author: number | User
published_at: string
status: 'draft' | 'published'
}
const client = createDirectus<Schema>('http://localhost:8055').with(rest())
const posts = await client.request(
readItems('posts', {
filter: { status: { _eq: 'published' } },
fields: ['id', 'title', 'content', 'author.*'],
})
)
Le hic ? Vous devez écrire et maintenir vous-même ces définitions de types (ou les générer avec des outils communautaires comme directus-typescript-gen). Les types ne sont pas dérivés du schéma automatiquement de la même manière que Payload le fait en première classe. C'est le compromis du database-first : la base de données ne sait rien de TypeScript.

Couche API et capacités de requête
Les deux génèrent des API REST et GraphQL, mais avec des saveurs différentes.
Payload vous donne :
- API REST avec contrôle de profondeur pour les relations
- API GraphQL (auto-générée à partir de votre config)
- API locale (requêtes de base de données directes, pas de surcharge HTTP)
- Opérateurs de requête complets : equals, not_equals, greater_than, in, contains, etc.
Directus vous donne :
- API REST avec sélection de champs granulaire
- API GraphQL (auto-générée à partir de l'introspection de schéma)
- SDK Directus (encapsule REST, typé si vous fournissez des interfaces)
- Filtrage riche avec
_eq,_neq,_gt,_in,_contains, opérateurs logiques_and/_or - Requêtes d'agrégation intégrées à l'API (count, sum, avg, etc.)
Directus a un léger avantage sur la flexibilité de l'API pour les requêtes complexes, en particulier les agrégations. Si vous avez besoin de faire des requêtes de style GROUP BY via l'API, Directus le gère nativement. Avec Payload, vous tomberiez généralement à la couche Drizzle ORM ou écriveriez un point de terminaison personnalisé.
L'avantage tueur de Payload est l'API locale. Quand votre CMS et votre frontend Next.js sont le même processus, vous sautez HTTP entièrement. Pour les pages rendues côté serveur, cela signifie des constructions plus rapides et une latence inférieure.
Panneau d'administration et édition de contenu
Le panneau d'administration de Payload 3.x est construit avec React et est livré en tant que partie de votre application Next.js. Il est personnalisable avec des composants React — vous pouvez remplacer pratiquement n'importe quelle partie de l'interface. L'éditeur de texte riche basé sur des blocs (construit sur Lexical à partir de v3) est puissant et extensible.
Le panneau d'administration de Directus est une application Vue.js autonome (Directus Data Studio). C'est poli, a un design visuel fort, et les utilisateurs non-techniques ont tendance à le comprendre rapidement. Le générateur de flux/d'automatisation dans Directus est considérablement plus visuel et accessible que le système de hooks de Payload.
| Fonctionnalité | Payload CMS | Directus |
|---|---|---|
| Framework d'administration | React (Next.js) | Vue.js (autonome) |
| Éditeur de texte riche | Basé sur Lexical | TipTap / WYSIWYG |
| Champs personnalisés | Composants React | Extensions Vue |
| Flux de travail/Automatisation | Hooks + points de terminaison personnalisés | Directus Flows (générateur visuel) |
| Localisation | i18n au niveau des champs intégré | i18n au niveau des champs intégré |
| Versioning du contenu | Brouillon/publication + versions | Versioning du contenu + révisions |
| Gestion des fichiers | Bibliothèque de médias intégrée | Bibliothèque de médias intégrée avec transformations |
Voici mon avis honnête : pour les équipes lourdes en développeurs, l'administration de Payload est plus naturelle à étendre car vous écrivez React. Pour les équipes où les éditeurs de contenu sont les utilisateurs primaires et vous voulez une UX sans friction, le panneau d'administration de Directus est légèrement plus accessible d'emblée.
Authentification et contrôle d'accès
Les deux systèmes ont une authentification mature, mais ils fonctionnent différemment.
Payload utilise l'authentification basée sur les collections. Vous marquez une collection comme collection d'authentification (généralement users), et elle obtient la connexion, l'inscription, la réinitialisation de mot de passe, la vérification d'email et les sessions basées sur JWT/cookie. Le contrôle d'accès est défini par collection et par champ en utilisant des fonctions :
{
slug: 'posts',
access: {
read: () => true, // Public
create: ({ req: { user } }) => Boolean(user), // Authentifié
update: ({ req: { user } }) => user?.role === 'admin',
delete: ({ req: { user } }) => user?.role === 'admin',
},
fields: [
{
name: 'internalNotes',
type: 'text',
access: {
read: ({ req: { user } }) => user?.role === 'admin',
},
},
],
}
C'est incroyablement puissant. Les fonctions de contrôle d'accès reçoivent le contexte de requête complet, donc vous pouvez implémenter n'importe quel modèle — RBAC, ABAC, multi-tenancy, sécurité au niveau des lignes.
Directus utilise un système de permissions basé sur les rôles configuré via le panneau d'administration. Vous créez des rôles, attribuez des permissions granulaires (CRUDS par collection), et ajoutez des permissions personnalisées avec des filtres. C'est visuel et intuitif, mais moins flexible pour les modèles complexes qui ne correspondent pas au modèle de rôle.
Pour la plupart des projets, les deux sont suffisants. Pour la SaaS multi-tenants ou la logique d'autorisation complexe, le contrôle d'accès basé sur le code de Payload est difficile à battre.
Performance et scalabilité
J'ai fait des tests de charge sur les deux dans des conditions réalistes. Voici ce que j'ai observé avec des backends PostgreSQL :
| Métrique | Payload CMS 3.x | Directus 11 |
|---|---|---|
| Lecture simple (élément unique) | ~2-5ms API locale, ~15-25ms REST | ~15-30ms REST |
| Requête de liste (100 éléments, pas de relations) | ~8-15ms API locale, ~30-50ms REST | ~25-50ms REST |
| Requête de liste (100 éléments, 2 niveaux de profondeur) | ~20-40ms API locale, ~60-100ms REST | ~50-120ms REST |
| Temps de démarrage à froid | ~3-6s (démarrage Next.js) | ~2-4s (autonome) |
| Baseline mémoire | ~200-350MB (avec Next.js) | ~150-250MB |
L'avantage de l'API locale de Payload est réel et significatif pour les charges de travail SSR/SSG. Quand vous générez 10 000 pages statiques, sauter HTTP pour chaque requête s'accumule rapidement.
Directus ne traîne pas non plus. Il gère bien les charges de travail REST à haut débit, et sa couche de mise en cache (soutenue par Redis) est mature.
Déploiement et hébergement
Payload 3.x est une application Next.js, ce qui signifie que vous pouvez la déployer n'importe où où Next.js s'exécute : Vercel, Netlify, AWS, Docker, etc. Payload Cloud (leur hébergement géré) commence à 30 $/mois pour les projets de production au début de 2026.
Directus s'exécute comme une application Node.js autonome. Docker est la méthode de déploiement recommandée. Directus Cloud commence à 29 $/mois. L'auto-hébergement sur un VPS est simple — c'est juste un conteneur Docker qui a besoin d'une connexion à une base de données.
Une chose à noter : puisque Payload 3.x est votre application Next.js, votre CMS et frontend se déploient ensemble. Cela simplifie l'infrastructure mais signifie que votre panneau d'administration CMS se met à l'échelle avec votre frontend. Pour les sites à haut trafic où le frontend et le CMS ont des besoins de mise à l'échelle très différents, vous voudrez peut-être envisager de les exécuter séparément.
Directus, étant un service séparé, sépare naturellement ces préoccupations. Votre frontend (que ce soit Next.js, Astro ou n'importe quoi d'autre) se connecte à Directus via HTTP. C'est une architecture headless plus traditionnelle.
Chez Social Animal, nous avons déployé les deux architectures pour les clients. L'approche Payload-in-Next.js fonctionne magnifiquement pour la plupart des sites marketing et des applications d'échelle moyenne. Pour les configurations d'entreprise avec plusieurs consommateurs frontend, l'approche Directus séparée peut être plus propre.
Tarification et licences en 2026
| Payload CMS | Directus | |
|---|---|---|
| Licence | MIT | GPL-3.0 (avec BSL pour les fonctionnalités Cloud) |
| Coût auto-hébergé | Gratuit | Gratuit |
| Hébergement cloud | À partir de 30 $/mo (Payload Cloud) | À partir de 29 $/mo (Directus Cloud) |
| Niveau entreprise | Tarification personnalisée | Tarification personnalisée (commence ~1 500 $/mo) |
| Fonctionnalités premium | Certaines fonctionnalités Cloud uniquement | Abonnement Directus+ (99 $/mo pour les extensions marketplace) |
Les deux sont véritablement open-source pour l'auto-hébergement. La licence MIT de Payload est plus permissive — vous pouvez l'intégrer dans des produits commerciaux sans restrictions. La licence GPL-3.0 de Directus signifie que les travaux dérivés doivent également être GPL, ce qui peut avoir de l'importance pour les produits SaaS.
Directus a introduit Directus+ fin 2025, un abonnement qui déverrouille les extensions marketplace premium et le support prioritaire. C'est optionnel mais certaines extensions plus avancées (comme l'assistant de contenu alimenté par IA) sont derrière ce paywall.
Quand choisir lequel
Choisissez Payload CMS quand :
- Vous construisez un nouveau projet à partir de zéro (greenfield)
- Votre équipe est lourde en TypeScript et veut le schéma-comme-code
- Vous utilisez Next.js et voulez l'intégration la plus étroite possible
- Vous avez besoin d'un contrôle d'accès complexe défini par code
- Vous voulez tout dans une unité déployable
- Vous valorisez la licence MIT
Choisissez Directus quand :
- Vous avez une base de données existante que vous devez gérer
- Votre équipe inclut des non-développeurs qui ont besoin de modifier les schémas
- Vous devez supporter plusieurs frontends (web, mobile, IoT) à partir d'un CMS
- Vous avez besoin d'un générateur de flux/d'automatisation visuel
- Vous avez besoin d'un support large de base de données (MySQL, MSSQL, Oracle, etc.)
- Vous préférez le CMS comme un service séparé et indépendant
Si vous pesez ces options pour un projet headless et voulez un deuxième avis, nous faisons des consultations en architecture CMS headless et pouvons vous aider à choisir le bon outil avant d'être trois mois avec le mauvais.
Pour les projets utilisant Astro comme framework frontend, l'approche API autonome de Directus s'associe naturellement, puisque Astro récupère les données au moment de la construction ou via des points de terminaison serveur. Payload fonctionne aussi, mais vous perdez l'avantage de l'API locale puisque Astro et Payload seraient des processus séparés.
FAQ
Payload CMS est-il vraiment gratuit en 2026 ? Oui. Payload CMS est sous licence MIT et totalement gratuit à auto-héberger. Payload Cloud est leur service d'hébergement géré payant, mais le CMS lui-même — y compris toutes les fonctionnalités de base — est open source. Il n'y a pas de portes de fonctionnalités sur la version auto-hébergée.
Directus peut-il fonctionner avec une base de données existante sans la modifier ?
Surtout oui. Directus peut introspect une base de données existante et créer une couche de gestion dessus. Il ajoute quelques tables système (préfixées par directus_) pour sa propre configuration, mais il ne modifie pas vos tables existantes. C'est l'un de ses plus forts différenciateurs.
Lequel est meilleur pour un développeur solo ? Payload CMS tend à être le préféré parmi les développeurs solo qui sont à l'aise avec TypeScript. Le flux de travail code-first signifie que vous pouvez configurer les collections rapidement, et les types auto-générés réduisent le boilerplate. Directus est meilleur si vous voulez une interface visuelle pour le prototypage rapide de schéma sans écrire de fichiers de configuration.
Puis-je utiliser Payload CMS sans Next.js ? À partir de Payload 3.x, Next.js est l'adaptateur principal et le panneau d'administration s'exécute sur Next.js. Cependant, les API REST et GraphQL fonctionnent avec n'importe quel frontend. Vous n'êtes pas verrouillé à Next.js pour votre site destiné aux consommateurs — vous avez juste besoin de Next.js pour exécuter l'administration de Payload. Il y a eu des discussions communautaires sur des adaptateurs supplémentaires (comme Nuxt), mais rien d'officiel pour le moment.
Comment Directus gère-t-il la localisation du contenu ?
Directus supporte les traductions au niveau des champs. Vous marquez les champs comme traductibles, configurez vos langues, et Directus gère le stockage des traductions dans une table connexe. L'API vous permet de demander du contenu dans des langues spécifiques via les paramètres ?fields et de langue. C'est bien implémenté et a été stable pendant des années.
Lequel a un meilleur support de plugins/extensions ? Directus a une plus grande place marketplace d'extensions, en particulier avec les ajouts de Directus+. Vous pouvez construire des interfaces personnalisées, des affichages, des points de terminaison, des hooks et des modules. Le modèle d'extension de Payload est basé sur les remplacements de composants React et les plugins — c'est puissant mais l'écosystème est plus petit. Les plugins de Payload ont tendance à être plus ciblés (plugin SEO, créateur de formulaires, redirects) tandis que les extensions Directus couvrent une plus large gamme.
Y a-t-il une différence de performance pour les grands ensembles de données ? Pour les ensembles de données avec des millions de lignes, les deux fonctionnent bien avec des index appropriés. Directus a un léger avantage sur la flexibilité de requête pure puisqu'il génère SQL plus directement à partir des requêtes API. La couche Drizzle ORM de Payload est efficace mais ajoute un petit coût d'abstraction. En pratique, votre tuning de base de données importe beaucoup plus que le CMS que vous choisissez. Les deux supportent le pooling de connexions et peuvent fonctionner avec des réplicas en lecture.
Puis-je migrer d'une à l'autre plus tard ? Vous pouvez, mais ce n'est pas trivial. Les données de contenu elles-mêmes (stockées dans PostgreSQL pour les deux) peuvent être migrées avec les outils standard de base de données. La partie plus difficile est de recréer vos définitions de schéma, vos règles de contrôle d'accès et n'importe quelle logique personnalisée. Si vous construisez pour une architecture headless, garder votre frontend découplé des API spécifiques au CMS (en utilisant une couche d'abstraction) rendra toute future migration de CMS significativement plus facile.