Payload CMS vs Directus 2026: ¿Code-First o Database-First?
Tu build de Next.js comienza el viernes. El cliente quiere control editorial completo, la base de datos debe mantenerse en casa, y tu dev principal se niega a tocar cualquier cosa sin autocompletado de TypeScript. Has descartado las plataformas SaaS propietarias y has llegado a dos contendientes headless open-source: Payload CMS y Directus. Ambos corren en Node.js. Ambos se despliegan rápido. Ambos te permiten auto-hospedarte. Pero uno te pide que definas tu schema en código antes de que la base de datos exista. El otro lee tu base de datos existente y construye la interfaz de administración alrededor de ella. Esa única bifurcación —code-first versus database-first— determinará si tu schema vive en control de versiones o se hace clic en la existencia a través de una interfaz, si tus tipos fluyen automáticamente a tu frontend o requieren un paso de sincronización manual, y si tu despliegue se siente como hacer push a un commit de Git o migrar una tabla de producción. Entonces, ¿cuál filosofía se ajusta a la forma en que tu equipo realmente trabaja?
He desplegado sitios de producción con ambos durante los últimos dos años. Aquí está lo que realmente pienso, no lo que dicen las páginas de marketing.
Tabla de Contenidos
- La Bifurcación de Filosofía Central
- Diseño de Schema: Code-First vs Database-First
- TypeScript y Experiencia del Desarrollador
- Capa de API y Capacidades de Consulta
- Panel de Administración y Edición de Contenido
- Autenticación y Control de Acceso
- Rendimiento y Escalabilidad
- Despliegue y Alojamiento
- Precios y Licencias en 2026
- Cuándo Elegir Cuál
- Preguntas Frecuentes

La Bifurcación de Filosofía Central
Permíteme establecer esto claramente porque es lo más importante que debes entender:
Payload CMS es code-first. Defines tu schema en archivos de configuración TypeScript. La base de datos se conforma a tu código.
Directus es database-first. Puedes apuntarlo a una base de datos existente e introspecciona el schema. La interfaz de administración se conforma a tu base de datos.
Ningún enfoque es objetivamente mejor. Pero uno será dramáticamente mejor para tu proyecto, y equivocarse en esto significa dolor después.
Si eres un desarrollador construyendo un proyecto greenfield y deseas que tu schema de CMS esté versionado junto con el código de tu aplicación, Payload se sentirá como en casa. Si tienes una base de datos PostgreSQL existente con 200 tablas y necesitas una capa de gestión de contenido encima, Directus te ahorrará semanas.
Diseño de Schema: Code-First vs Database-First
Enfoque Code-First de Payload
En Payload 3.x (la versión principal actual a partir de 2026), defines colecciones en archivos de configuración 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',
},
],
}
Esta configuración es tu fuente de verdad. Cuando Payload inicia, genera migraciones de base de datos automáticamente (Payload 3.x usa Drizzle ORM bajo el capó con soporte para PostgreSQL o SQLite, y aún soporta MongoDB). Tu schema vive en Git. Revisas cambios de schema en PRs. Es el mismo flujo de trabajo que usarías para código de aplicación, y ese es el punto.
Payload también genera automáticamente tipos TypeScript de estas configuraciones. Así que cuando consultas posts en tu frontend de Next.js, obtienes seguridad de tipos completa sin mantener definiciones de tipos separadas.
Enfoque Database-First de Directus
Directus toma la posición opuesta. Puedes:
- Apuntar Directus a una base de datos existente y lee el schema
- Crear colecciones a través de la interfaz de administración, que genera migraciones SQL
- Usar el SDK de Directus para gestionar el schema programáticamente
// Creando una colección vía SDK de Directus
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 (lanzado a finales de 2025) mejoró significativamente las herramientas de migración de schema. Ahora puedes exportar e importar snapshots de schema como archivos YAML, lo que hace el control de versiones más práctico que antes:
# Exportar schema actual
npx directus schema snapshot ./schema-snapshot.yaml
# Aplicar diff de schema a otro ambiente
npx directus schema apply ./schema-snapshot.yaml
Pero aquí está la verdad honesta: incluso con estas mejoras, la gestión de schema de Directus no se siente tan natural en un flujo de Git como el enfoque de Payload. Estás capturando estado en lugar de declarar intención.
Tabla de Comparación de Schema
| Aspecto | Payload CMS | Directus |
|---|---|---|
| Fuente de verdad del schema | Archivos de configuración TypeScript | La base de datos misma |
| Versionado del schema | Flujo nativo de Git | Snapshots YAML (mejorado en v11) |
| Soporte de base de datos existente | Limitado (ruta de migración) | Excelente (introspección) |
| Tipos generados automáticamente | Sí, desde config | Sí, vía SDK + CLI |
| Soporte de base de datos | PostgreSQL, SQLite, MongoDB | PostgreSQL, MySQL, MariaDB, SQLite, MS SQL, CockroachDB, OracleDB |
| ORM / capa de consulta | Drizzle ORM (v3) | Motor de consulta personalizado (basado en Knex) |
| Generación de migraciones | Automática desde cambios de config | Snapshots de diff de schema |
TypeScript y Experiencia del Desarrollador
La Historia de TypeScript de Payload
Payload es TypeScript hasta los huesos. Todo el proyecto está escrito en TypeScript, configurado en TypeScript, y genera TypeScript. Cuando ejecutas payload generate:types, obtienes interfaces para cada colección:
// Auto-generated
export interface Post {
id: string
title: string
content?: RichTextContent
author?: string | User
publishedAt?: string
status?: 'draft' | 'published'
createdAt: string
updatedAt: string
}
Estos tipos fluyen a través de tu Local API, respuestas de REST API, y consultas GraphQL. En Payload 3.x, ya que corre dentro de tu aplicación Next.js, puedes importar y usar estos tipos directamente. No se necesita SDK separado. Sin llamadas API para renderizado del lado del servidor — estás consultando la base de datos directamente:
// En un Componente de Servidor de 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á completamente tipado como Post[]
return <PostList posts={posts.docs} />
}
Esta es genuinamente una excelente experiencia de desarrollo. Sin saltos de red, tipos completos, y es solo... funciones.
La Historia de TypeScript de Directus
Directus ha mejorado significativamente su soporte de TypeScript. El paquete @directus/sdk soporta parámetros de tipo genérico:
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.*'],
})
)
La trampa? Tienes que escribir y mantener esas definiciones de tipos tú mismo (o generarlas con herramientas de comunidad como directus-typescript-gen). Los tipos no se derivan del schema automáticamente de la misma manera de primera clase que lo hace Payload. Este es el trade-off de database-first: la base de datos no sabe sobre TypeScript.

Capa de API y Capacidades de Consulta
Ambos generan APIs REST y GraphQL, pero con sabores diferentes.
Payload te da:
- API REST con control de profundidad para relaciones
- API GraphQL (auto-generada desde tu config)
- Local API (consultas de base de datos directas, sin overhead HTTP)
- Operadores de consulta completos: equals, not_equals, greater_than, in, contains, etc.
Directus te da:
- API REST con selección de campo granular
- API GraphQL (auto-generada desde introspección de schema)
- SDK de Directus (envuelve REST, tipado si proporcionas interfaces)
- Filtrado rico con
_eq,_neq,_gt,_in,_contains, operadores lógicos_and/_or - Consultas de agregación incorporadas en la API (count, sum, avg, etc.)
Directus tiene una ligera ventaja en flexibilidad de API para consultas complejas, especialmente agregaciones. Si necesitas hacer consultas de estilo GROUP BY a través de la API, Directus lo maneja nativamente. Con Payload, típicamente caerías a la capa Drizzle ORM o escribirías un endpoint personalizado.
La ventaja asesina de Payload es la Local API. Cuando tu CMS y tu frontend de Next.js están en el mismo proceso, saltas HTTP completamente. Para páginas renderizadas en el servidor, esto significa builds más rápidos y menor latencia.
Panel de Administración y Edición de Contenido
El panel de administración de Payload 3.x está construido con React y se entrega como parte de tu aplicación Next.js. Es personalizable con componentes React — puedes sobrescribir virtualmente cualquier parte de la interfaz. El editor de texto enriquecido basado en bloques (construido en Lexical a partir de v3) es poderoso y extensible.
El panel de administración de Directus es una aplicación Vue.js independiente (Directus Data Studio). Es pulida, tiene un fuerte diseño visual, y los usuarios no técnicos tienden a aprenderla rápidamente. El constructor de flow/automatización en Directus es notablemente más visual y accesible que el sistema de hooks de Payload.
| Característica | Payload CMS | Directus |
|---|---|---|
| Marco de administración | React (Next.js) | Vue.js (independiente) |
| Editor de texto enriquecido | Basado en Lexical | TipTap / WYSIWYG |
| Campos personalizados | Componentes React | Extensiones Vue |
| Workflow/Automatización | Hooks + endpoints personalizados | Directus Flows (constructor visual) |
| Localización | i18n a nivel de campo incorporado | i18n a nivel de campo incorporado |
| Versionado de contenido | Borrador/publicación + versiones | Versionado de contenido + revisiones |
| Gestión de archivos | Librería de medios incorporada | Librería de medios incorporada con transformaciones |
Aquí está mi opinión honesta: para equipos pesados en desarrollo, la administración de Payload es más natural para extender porque estás escribiendo React. Para equipos donde los editores de contenido son los usuarios principales y deseas UX de baja fricción, el panel de administración de Directus es ligeramente más accesible lista para usar.
Autenticación y Control de Acceso
Ambos sistemas tienen autenticación madura, pero funcionan de manera diferente.
Payload usa autenticación basada en colecciones. Marcas una colección como colección de autenticación (típicamente users), y obtiene login, registro, restablecimiento de contraseña, verificación de email, y sesiones basadas en JWT/cookies. El control de acceso se define por colección y por campo usando funciones:
{
slug: 'posts',
access: {
read: () => true, // Público
create: ({ req: { user } }) => Boolean(user), // Autenticado
update: ({ req: { user } }) => user?.role === 'admin',
delete: ({ req: { user } }) => user?.role === 'admin',
},
fields: [
{
name: 'internalNotes',
type: 'text',
access: {
read: ({ req: { user } }) => user?.role === 'admin',
},
},
],
}
Esto es increíblemente poderoso. Las funciones de control de acceso reciben el contexto de solicitud completo, así que puedes implementar cualquier patrón — RBAC, ABAC, multi-arrendamiento, seguridad a nivel de fila.
Directus usa un sistema de permisos basado en roles configurado a través del panel de administración. Creas roles, asignas permisos granulares (CRUDS por colección), y añades permisos personalizados con filtros. Es visual e intuitivo, pero menos flexible para patrones complejos que no se ajustan al modelo de roles.
Para la mayoría de proyectos, ambos son suficientes. Para SaaS multi-arrendador o lógica de autorización compleja, el control de acceso basado en código de Payload es difícil de superar.
Rendimiento y Escalabilidad
He hecho pruebas de carga en ambos bajo condiciones realistas. Aquí está lo que observé con backends PostgreSQL:
| Métrica | Payload CMS 3.x | Directus 11 |
|---|---|---|
| Lectura simple (artículo único) | ~2-5ms local API, ~15-25ms REST | ~15-30ms REST |
| Consulta de lista (100 artículos, sin relaciones) | ~8-15ms local API, ~30-50ms REST | ~25-50ms REST |
| Consulta de lista (100 artículos, 2 niveles de profundidad) | ~20-40ms local API, ~60-100ms REST | ~50-120ms REST |
| Tiempo de inicio en frío | ~3-6s (arranque de Next.js) | ~2-4s (independiente) |
| Línea de base de memoria | ~200-350MB (con Next.js) | ~150-250MB |
La ventaja de la Local API de Payload es real y significativa para cargas de trabajo SSR/SSG. Cuando estás generando 10,000 páginas estáticas, saltar HTTP para cada consulta se suma rápidamente.
Directus no es ningún perezoso. Maneja bien cargas de trabajo REST de alto rendimiento, y su capa de caché (respaldada por Redis) es madura.
Despliegue y Alojamiento
Payload 3.x es una aplicación Next.js, lo que significa que puedes desplegarla en cualquier lugar donde corra Next.js: Vercel, Netlify, AWS, Docker, etc. Payload Cloud (su alojamiento gestionado) comienza en $30/mes para proyectos de producción a partir de principios de 2026.
Directus corre como una aplicación Node.js independiente. Docker es el método de despliegue recomendado. Directus Cloud comienza en $29/mes. El auto-alojamiento en un VPS es directo — es solo un contenedor Docker que necesita una conexión de base de datos.
Una cosa que vale la pena notar: porque Payload 3.x es tu aplicación Next.js, tu CMS y frontend se despliegan juntos. Esto simplifica la infraestructura pero significa que tu panel de administración de CMS se escala con tu frontend. Para sitios de alto tráfico donde el frontend y el CMS tienen muy diferentes necesidades de escalado, podrías querer considerar ejecutarlos por separado.
Directus, siendo un servicio separado, naturalmente separa estas preocupaciones. Tu frontend (ya sea Next.js, Astro, o cualquier otra cosa) se conecta a Directus por HTTP. Esta es una arquitectura headless más tradicional.
En Social Animal, hemos desplegado ambas arquitecturas para clientes. El enfoque de Payload-en-Next.js funciona bellamente para la mayoría de sitios de marketing y aplicaciones de escala media. Para configuraciones empresariales con múltiples consumidores de frontend, el enfoque separado de Directus puede ser más limpio.
Precios y Licencias en 2026
| Payload CMS | Directus | |
|---|---|---|
| Licencia | MIT | GPL-3.0 (con BSL para características de Cloud) |
| Costo de auto-alojamiento | Gratis | Gratis |
| Alojamiento en la nube | Desde $30/mes (Payload Cloud) | Desde $29/mes (Directus Cloud) |
| Nivel empresarial | Precios personalizados | Precios personalizados (comienza ~$1,500/mes) |
| Características premium | Algunas características solo en Cloud | Suscripción Directus+ ($99/mes para extensiones de marketplace) |
Ambos son genuinamente open-source para auto-alojamiento. La licencia MIT de Payload es más permisiva — puedes incrustarlo en productos comerciales sin restricciones. La licencia GPL-3.0 de Directus significa que los trabajos derivados también deben ser GPL, lo que puede importar para productos SaaS.
Directus introdujo Directus+ a finales de 2025, una suscripción que desbloquea extensiones premium de marketplace y soporte prioritario. Es opcional pero algunas de las extensiones más avanzadas (como el asistente de contenido AI) están detrás de este muro de pago.
Cuándo Elegir Cuál
Elige Payload CMS cuando:
- Estás construyendo un nuevo proyecto desde cero (greenfield)
- Tu equipo es pesado en TypeScript y quiere schema-como-código
- Estás usando Next.js y quieres la integración más ajustada posible
- Necesitas control de acceso complejo, definido en código
- Quieres todo en una unidad deployable
- Valoras las licencias MIT
Elige Directus cuando:
- Tienes una base de datos existente que necesitas gestionar
- Tu equipo incluye no-desarrolladores que necesitan modificar schemas
- Necesitas soportar múltiples frontends (web, móvil, IoT) desde un CMS
- Necesitas un constructor de automatización/flow visual
- Necesitas soporte amplio de base de datos (MySQL, MSSQL, Oracle, etc.)
- Prefieres el CMS como un servicio separado e independiente
Si estás pesando estas opciones para un proyecto headless y quieres una segunda opinión, hacemos consultoría de arquitectura headless CMS y podemos ayudarte a elegir la herramienta correcta antes de estar tres meses en la herramienta equivocada.
Para proyectos usando Astro como marco de frontend, el enfoque de API independiente de Directus se empareja naturalmente, ya que Astro obtiene datos en tiempo de compilación o vía endpoints de servidor. Payload también funciona, pero pierdes la ventaja de la Local API ya que Astro y Payload serían procesos separados.
Preguntas Frecuentes
¿Es Payload CMS realmente gratis en 2026? Sí. Payload CMS está licenciado bajo MIT y es completamente gratuito para auto-alojar. Payload Cloud es su servicio de alojamiento gestionado de pago, pero el CMS en sí — incluyendo todas las características principales — es open source. No hay puertas de características en la versión auto-alojada.
¿Puede Directus funcionar con una base de datos existente sin modificarla?
Mayormente sí. Directus puede introspeccionar una base de datos existente y crear una capa de gestión encima. Añade algunas tablas del sistema (con prefijo directus_) para su propia configuración, pero no modifica tus tablas existentes. Este es uno de sus diferenciadores más fuertes.
¿Cuál es mejor para un desarrollador en solitario? Payload CMS tiende a ser el favorito entre desarrolladores en solitario que se sienten cómodos con TypeScript. El flujo de trabajo code-first significa que puedes configurar colecciones rápidamente, y los tipos generados automáticamente reducen el boilerplate. Directus es mejor si quieres una interfaz visual para prototipado rápido de schema sin escribir archivos de config.
¿Puedo usar Payload CMS sin Next.js? A partir de Payload 3.x, Next.js es el adaptador primario y el panel de administración corre en Next.js. Sin embargo, las APIs REST y GraphQL funcionan con cualquier frontend. No estás bloqueado a Next.js para tu sitio de cara al consumidor — solo necesitas Next.js para ejecutar la administración de Payload. Ha habido discusiones comunitarias sobre adaptadores adicionales (como Nuxt), pero nada oficial aún.
¿Cómo maneja Directus la localización de contenido?
Directus soporta traducciones a nivel de campo. Marcas campos como traducibles, configuras tus idiomas, y Directus maneja almacenar traducciones en una tabla relacionada. La API te permite solicitar contenido en idiomas específicos vía los parámetros ?fields y idioma. Está bien implementado y ha sido estable durante años.
¿Cuál tiene mejor soporte de plugin/extensión? Directus tiene un marketplace de extensiones más grande, especialmente con las adiciones de Directus+. Puedes construir interfaces personalizadas, displays, endpoints, hooks, y módulos. El modelo de extensión de Payload se basa en sobrescrituras de componentes React y plugins — es poderoso pero el ecosistema es más pequeño. Los plugins de Payload tienden a ser más enfocados (plugin SEO, constructor de formularios, redirecciones) mientras que las extensiones de Directus cubren un rango más amplio.
¿Hay una diferencia de rendimiento para grandes conjuntos de datos? Para conjuntos de datos con millones de filas, ambos funcionan bien cuando están apropiadamente indexados. Directus tiene una ligera ventaja en flexibilidad de consulta cruda ya que genera SQL más directamente desde consultas de API. La capa Drizzle ORM de Payload es eficiente pero añade un pequeño costo de abstracción. En la práctica, tu sintonización de base de datos importa mucho más que cuál CMS elijas. Ambos soportan agrupación de conexiones y pueden funcionar con réplicas de lectura.
¿Puedo migrar de uno a otro después? Puedes, pero no es trivial. Los datos de contenido en sí (almacenados en PostgreSQL para ambos) pueden ser migrados con herramientas estándar de base de datos. La parte más difícil es recrear tus definiciones de schema, reglas de control de acceso, y cualquier lógica personalizada. Si estás construyendo para una arquitectura headless, mantener tu frontend desacoplado de APIs específicas de CMS (usando una capa de abstracción) hará que cualquier migración futura de CMS sea significativamente más fácil.