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

Payload CMS vs Directus en 2026: Code-First vs Database-First

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:

  1. Apuntar Directus a una base de datos existente y lee el schema
  2. Crear colecciones a través de la interfaz de administración, que genera migraciones SQL
  3. 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.

Payload CMS vs Directus en 2026: Code-First vs Database-First - arquitectura

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.