Saltar al contenido

Better Auth vs Clerk: por qué elegimos Better Auth

Para CTO y desarrolladoresDecisiones de CTO

Filip PapranecFundador de Digitaliko

Better Auth vs Clerk. Ilustración: a la izquierda una tabla de usuarios dentro de su propia base de datos, a la derecha un directorio de usuarios alojado detrás de una API, con la pregunta de dónde viven sus sesiones.Better Auth vs Clerk. Ilustración: a la izquierda una tabla de usuarios dentro de su propia base de datos, a la derecha un directorio de usuarios alojado detrás de una API, con la pregunta de dónde viven sus sesiones.

Better Auth vs Clerk se reduce a una pregunta: ¿dónde viven sus usuarios y sesiones? Clerk los guarda en su servicio alojado. Better Auth los escribe en su propia base de datos, como tablas normales junto al resto de su aplicación.

Pasamos de NextAuth a Better Auth en cada aplicación nueva y nunca elegimos Clerk. Primero, un límite honesto: no hemos usado Clerk en producción. Así que esto no es un benchmark. Es por qué no lo elegimos, con las configuraciones que de verdad usamos.

¿Qué diferencia hay entre Better Auth y Clerk?

Better Auth es una librería. Se describe a sí misma como "a framework-agnostic, universal authentication and authorization framework for TypeScript" (documentación de Better Auth, a 24/10/2026). Tiene licencia MIT. Clerk es un servicio alojado con componentes de inicio de sesión ya hechos y un panel de usuarios.

Better AuthClerk
Qué esLibrería TypeScript en su repositorioServicio de autenticación alojado con componentes de interfaz
Dónde viven usuarios y sesionesTablas en su base de datosInfraestructura de Clerk
PrecioMIT, usted paga su base de datos y su correoGratis hasta 50.000 usuarios retenidos al mes por aplicación, después de pago (precios, a 24/10/2026)
Interfaz de inicio de sesiónLa construye ustedComponentes ya hechos
Parches de seguridadUsted actualiza el paquete y despliegaLos publica Clerk
Correos de verificación y magic linksSu servicio de correoLos envía Clerk
SalidaNo hay nada que dejar, es su esquemaExportación de usuarios con contraseñas con hash, después recablear la interfaz y las comprobaciones de sesión

Las filas que lo decidieron para nosotros son la segunda y la tercera. Nuestros clientes son dueños de su código, sus datos y su infraestructura desde el primer día. Una tabla de usuarios en servidores de otro, facturada por usuario, no encaja con eso.

¿Por qué pasamos de NextAuth a Better Auth?

Nuestras aplicaciones de clientes más antiguas usan NextAuth v4 con el adaptador de Prisma. Siguen funcionando y no las tocamos. Una autenticación que funciona no es algo que reescribamos para un artículo.

Para las aplicaciones nuevas, la decisión se simplificó en septiembre de 2025. Auth.js, el proyecto antes llamado NextAuth.js, pasó al equipo de Better Auth. Su anuncio lo dice claramente:

We strongly recommend new projects to start with Better Auth unless there are some very specific feature gaps.

Bereket Engida
Better Auth, Auth.js is now part of Better Auth (22/09/2025)

La carencia que mencionan son las sesiones sin estado y sin base de datos. Nosotros queremos la base de datos de todos modos, así que nunca nos afectó.

¿Cómo es Better Auth en una aplicación real?

Este es el paquete de autenticación de nuestra plantilla base, algo recortado. TanStack Start en Cloudflare Workers, Drizzle sobre D1:

import { betterAuth } from 'better-auth'
import { drizzleAdapter } from 'better-auth/adapters/drizzle'
import { tanstackStartCookies } from 'better-auth/tanstack-start'
import { checkout, polar, portal } from '@polar-sh/better-auth'

export function createAuth() {
  const db = createDb()
  const plugins = [tanstackStartCookies()]

  // Cobros solo cuando la aplicación tiene un token de pagos.
  if (env.POLAR_ACCESS_TOKEN) {
    plugins.push(polar({ client: polarClient, createCustomerOnSignUp: true, use: [checkout({ /* productos */ }), portal()] }))
  }

  return betterAuth({
    database: drizzleAdapter(db, { provider: 'sqlite', schema }),
    trustedOrigins: [env.CORS_ORIGIN],
    emailAndPassword: { enabled: true },
    socialProviders: { /* Google y GitHub, solo cuando sus claves están configuradas */ },
    secret: env.BETTER_AUTH_SECRET,
    baseURL: env.BETTER_AUTH_URL,
    plugins,
  })
}

El esquema también es nuestro. Usuarios y sesiones son tablas de Drizzle como cualquier otra:

const user = sqliteTable('user', {
  id: text('id').primaryKey(),
  name: text('name').notNull(),
  email: text('email').notNull().unique(),
  emailVerified: integer('email_verified', { mode: 'boolean' }).default(false).notNull(),
})

const session = sqliteTable('session', {
  id: text('id').primaryKey(),
  token: text('token').notNull().unique(),
  expiresAt: integer('expires_at', { mode: 'timestamp_ms' }).notNull(),
  userId: text('user_id').notNull().references(() => user.id, { onDelete: 'cascade' }),
})
Better Auth vs Clerk en dos ventanas. A la izquierda, Better Auth: las tablas de usuarios, sesiones y cuentas están en su propia base de datos junto a las tablas de la aplicación, y plugins como passkeys, autenticación en dos pasos y organizaciones se ejecutan como código en su repositorio. A la derecha, Clerk: un directorio de usuarios alojado con interfaz de inicio de sesión ya hecha, facturado por usuario retenido al mes, y su aplicación se comunica con él mediante una API.Better Auth vs Clerk en dos ventanas. A la izquierda, Better Auth: las tablas de usuarios, sesiones y cuentas están en su propia base de datos junto a las tablas de la aplicación, y plugins como passkeys, autenticación en dos pasos y organizaciones se ejecutan como código en su repositorio. A la derecha, Clerk: un directorio de usuarios alojado con interfaz de inicio de sesión ya hecha, facturado por usuario retenido al mes, y su aplicación se comunica con él mediante una API.

Esa es la diferencia práctica. Un registro creado por un usuario es una clave foránea a user.id en la misma base de datos. Un informe de "quién hizo qué" es un único JOIN de SQL, no una llamada a una API externa más un proceso de sincronización.

¿Cómo pasa la autenticación a formar parte de su propio código?

Nuestra aplicación interna de control muestra hasta dónde llega esto. Solo una lista corta de personas puede registrarse, y todas a través de GitHub. Ningún ajuste de un proveedor de autenticación hace eso. Son unas pocas líneas en un hook de base de datos:

return betterAuth({
  database: drizzleAdapter(db, { provider: 'sqlite', schema }),
  emailAndPassword: { enabled: false },
  databaseHooks: {
    user: {
      create: {
        before: async (user) => {
          if (allowedEmails.length > 0 && !allowedEmails.includes(user.email.toLowerCase())) return false
        },
      },
    },
  },
  socialProviders: { github: { clientId, clientSecret, scope: ['repo', 'read:user', 'user:email'] } },
})

Qué ocurre en un registro:

  1. Inicio de sesión con GitHub

    La persona inicia sesión con GitHub. La aplicación pide acceso a los repositorios, porque el panel lee issues y pull requests.

  2. El hook se ejecuta antes de la inserción

    databaseHooks.user.create.before recibe al nuevo usuario antes de que se escriba.

  3. No está en la lista: no hay usuario

    Devolver false detiene la inserción. No hay fila de usuario ni sesión.

  4. Está en la lista: una fila de sesión

    El usuario y la sesión quedan en la propia base de datos D1 de la aplicación, legibles con cualquier cliente SQL.

La lista de permitidos es una variable de entorno. Cambiarla es un despliegue, revisado como cualquier otro cambio. Con un servicio alojado, la misma regla viviría en un panel o en un webhook fuera del repositorio.

¿Qué plugins de Better Auth usamos en producción?

Cada plugin es código en el repositorio, así que la lista es fácil de comprobar:

  • Nuestra plantilla base: tanstackStartCookies y el plugin de cobros de Polar (checkout y portal de cliente, con un cliente creado al registrarse). Polar solo se añade cuando existe el token.
  • Una aplicación web de un cliente: Better Auth dentro de Payload CMS, con admin, organization, twoFactor, emailOTP, magicLink, multiSession y el plugin de passkeys.
  • El marketplace online de un cliente: un servicio de autenticación separado sobre MongoDB con magicLink y oidcProvider. Las demás aplicaciones del marketplace inician sesión a través de él, como con cualquier proveedor OpenID Connect.

Tres bases de datos, tres configuraciones, una librería. Es lo que más valoramos: la misma librería encaja con SQLite en el edge, Postgres detrás de un CMS y MongoDB en un servicio separado.

¿Cuándo es Clerk la mejor opción?

Clerk tiene sentido cuando quiere el inicio de sesión listo esta semana y nadie del equipo debe mantener código de autenticación. Los componentes ya hechos le ahorran las pantallas. Clerk envía los correos y parchea el servicio. Para un prototipo, el plan gratuito es generoso: 50.000 usuarios retenidos al mes por aplicación, Pro a 25 $ al mes y 0,02 $ por usuario del 50.001 al 100.000 (precios de Clerk, a 24/10/2026).

La dependencia es menor de lo que se cree. Clerk permite a los administradores exportar usuarios, incluidas las contraseñas con hash, como CSV (documentación de Clerk, a 24/10/2026). Los datos no quedan secuestrados. Lo que cuesta trabajo es todo lo que está conectado a ellos: la interfaz de inicio de sesión, las comprobaciones de sesión en el servidor y los datos de usuario que haya copiado a sus propias tablas.

Un dato más que conviene sopesar. Better Auth se unió a Vercel el 7 de julio de 2026. Su publicación dice: "Vercel shares our commitment to keeping auth open source, framework and platform agnostic." (blog de Better Auth). La licencia MIT sigue siendo la que es. Lo anotamos como anotamos cualquier cambio de propietario de una dependencia de la que dependemos.

¿Qué asume cuando la autenticación es suya?

Ser dueño de la autenticación no sale gratis en trabajo. El trabajo pasa a su equipo. Antes de elegir Better Auth, repase esta lista:

El último punto es el seguro más barato. Nuestra plantilla base ejecuta pruebas de Playwright exactamente para eso: el formulario de login se muestra, el registro funciona y el panel redirige al login sin sesión.

Cómo exponemos los datos de la aplicación a agentes de IA sobre esta autenticación lo explicamos en Cómo construir un servidor MCP, y cuándo no hacerlo.

¿Necesita una autenticación que se quede en su base de datos?

Construimos aplicaciones web en las que usuarios, sesiones y permisos viven en la propia base de datos del cliente, como parte del desarrollo de aplicaciones web a medida. El código, los datos y la infraestructura pertenecen al cliente desde el primer día. La IA escribe la mayor parte de nuestro código. Un senior revisa cada cambio y responde de lo que corre en producción. Desde 2023 hemos entregado más de 15 proyectos en producción.

Le respondemos en un plazo de dos días hábiles con algunas preguntas sobre su trabajo. Después acordamos qué hacemos primero.

Si prefiere hablar antes, reserve una llamada introductoria de 15 minutos.

¿Dónde viven hoy sus usuarios, y podría consultarlos con un único JOIN de SQL?

En resumen

  • Better Auth guarda usuarios y sesiones en su base de datos. Clerk los guarda en su servicio alojado.
  • Pasamos de NextAuth a Better Auth en las aplicaciones nuevas y dejamos como están las que funcionan con NextAuth.
  • Con Better Auth, reglas como una lista de correos permitidos son unas pocas líneas en su repositorio.
  • Clerk encaja cuando nadie debe mantener código de autenticación. Puede exportar los usuarios después, pero recablear cuesta trabajo.

Preguntas frecuentes

¿Qué diferencia hay entre Better Auth y Clerk?

Better Auth es una librería TypeScript de código abierto que guarda usuarios y sesiones en su propia base de datos. Clerk es un servicio alojado que los guarda por usted y le da una interfaz de inicio de sesión ya hecha. Se elige entre control y ninguna factura por usuario, o menos código propio que mantener.

¿Better Auth es gratis?

Sí. Better Auth tiene licencia MIT. Usted paga aquello sobre lo que funciona: su base de datos, su hosting y el servicio de correo que envía los enlaces de verificación y los magic links.

¿Cuánto cuesta Clerk?

A 24/10/2026, el plan Hobby de Clerk es gratuito con un límite de 50.000 usuarios retenidos al mes por aplicación, Pro cuesta 25 $ al mes (20 $ con facturación anual) y los usuarios del 50.001 al 100.000 cuestan 0,02 $ al mes cada uno. Consulte las cifras actuales en clerk.com/pricing.

¿Debería migrar de NextAuth a Better Auth?

En proyectos nuevos, sí: Auth.js lo mantiene ahora el equipo de Better Auth, y ellos recomiendan Better Auth para trabajo nuevo. Una aplicación con NextAuth que funciona no la migramos solo por migrar. Cambiamos cuando la aplicación necesita una función que NextAuth no tiene.

¿Puedo dejar Clerk más adelante?

Sí. Clerk permite a los administradores exportar los usuarios, incluidas las contraseñas con hash, como CSV desde el panel. Lo que cuesta trabajo es el resto: la interfaz de inicio de sesión, las comprobaciones de sesión y los datos de usuario que haya sincronizado en sus propias tablas.

Pregunte a una IA sobre este artículo

La IA también tiene en cuenta nuestros otros artículos y la experiencia de proyectos reales.

ChatGPTClaudePerplexity
Engineering

Más artículos

Decisiones de CTO

¿Refactorizar o reescribir desde cero? Cómo decidir

Refactorice cuando el código hace lo correcto, pero mal. Reescriba cuando hace lo incorrecto o el código no es suyo. Una tabla de decisión para CTO y una forma de hacerlo sin detener el roadmap.

Decisiones de CTO

Deuda técnica: cómo medirla y qué corregir primero

La deuda técnica se mide con el historial de git y los errores, sin herramientas caras. Corrija primero el código que más cambia y bloquea el roadmap, no el más feo. Una guía para CTO.

Decisiones de CTO

¿Body shopping o un desarrollador sénior en su equipo?

El body shopping le da horas de desarrollador que gestiona usted. Un sénior en su equipo le da tareas entregadas y un equipo que aprende a trabajar con IA. Comparado con el outsourcing y la contratación, para CTO.