Skip to main content

Guide

OpenAuth vs Better Auth vs Auth.js v6: Self-Hosted Auth in 2026

OpenAuth, Better Auth, and Auth.js v6 compared for self-hosted TypeScript auth: OAuth, sessions, MFA, and stack fit.

·PkgPulse Team·
0

TL;DR

Better Auth is the all-in-one default for 2026: framework-agnostic, plugin-rich (passkeys, MFA, multi-tenant orgs, magic links), with the smoothest TypeScript developer experience. OpenAuth (from the SST team) is the right call when you want a standalone OAuth/OIDC server you can deploy as its own service. Auth.js v6 (the rebrand of NextAuth) remains the path of least resistance specifically inside Next.js, especially when your auth needs are mostly social login + sessions. All three avoid the per-MAU pricing of hosted players. Choose based on whether you want auth as an embedded library (Better Auth, Auth.js) or as a separate service (OpenAuth).

Quick Verdict

OpenAuthBetter AuthAuth.js v6
ArchitectureStandalone OAuth/OIDC serverEmbedded libraryEmbedded library
Framework couplingNoneFramework-agnosticNext-first, others supported
Built-in MFA / passkeysLimitedYesPlugin-based
Multi-tenant orgsDIYBuilt-inDIY
OAuth as identity providerYes (you ARE the IdP)NoNo
Session storageDIYPluggable (DB, KV, JWT)Pluggable (DB, JWT)
DatabaseDIYDrizzle, Prisma, Mongo, KyselyDrizzle, Prisma, Mongo
Best for"I want my own IdP"Most TypeScript appsExisting Next.js apps

Key Takeaways

  • The split is "service vs library". OpenAuth runs as its own deploy. Better Auth and Auth.js are libraries that live inside your app process.
  • Better Auth has won the "best DX" slot for embedded auth. Plugin breadth, type safety, and adapter coverage have outpaced Auth.js v6 for non-Next stacks.
  • Auth.js v6 is the right keep-don't-rewrite call. If you're already on NextAuth and your needs are stable, the v6 upgrade gives you the cleanup without a migration.
  • None of these solve enterprise SSO out of the box. SAML / SCIM and the enterprise admin surface still push teams toward WorkOS, Stytch, or Clerk at the upper end of the market.

What Each Library Actually Is

Better Auth

A framework-agnostic auth library written in TypeScript with a plugin architecture. The core surface (createAuth({...})) handles email/password, sessions, and OAuth. Plugins layer on passkeys, magic links, organizations + invitations, MFA (TOTP), API keys, rate limiting, and more.

import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { passkey, organization, twoFactor } from "better-auth/plugins";

export const auth = betterAuth({
  database: drizzleAdapter(db, { provider: "pg" }),
  emailAndPassword: { enabled: true },
  socialProviders: {
    github: { clientId: process.env.GITHUB_ID!, clientSecret: process.env.GITHUB_SECRET! },
  },
  plugins: [passkey(), organization(), twoFactor()],
});

Adapter coverage: Next.js, Hono, Elysia, SvelteKit, Astro, TanStack Start. Type-safety is the standout — the client SDK is fully typed against the server config.

OpenAuth

OpenAuth is not an embedded auth library. It's a standalone OAuth 2.1 / OIDC server you run yourself (as a Worker, on AWS, or wherever). Your apps then act as OAuth clients.

import { issuer } from "@openauthjs/openauth";
import { GithubAdapter } from "@openauthjs/openauth/adapter/github";
import { handle } from "hono/aws-lambda";

const app = issuer({
  providers: { github: GithubAdapter({ clientID, clientSecret, scopes: ["user:email"] }) },
  storage: MemoryStorage(), // or DynamoDB, KV, etc.
  subjects: { user: { type: "object", properties: { id: { type: "string" } } } },
});

export const handler = handle(app);

The model is "you become your own identity provider". This is right when:

  • You have multiple frontends (web, mobile, CLI) that all need to share auth.
  • You want full control over the OAuth flows.
  • You're comfortable running auth as a separate deployment.

It's wrong when you want auth to feel like a library you import and forget about.

Auth.js v6

The rename of NextAuth into a more framework-neutral package, with v6 as the cleanup release. Adapter and provider catalogs are extensive; the developer experience inside Next.js is still where Auth.js shines hardest.

// auth.ts
import NextAuth from "next-auth";
import GitHub from "next-auth/providers/github";
import { DrizzleAdapter } from "@auth/drizzle-adapter";

export const { auth, handlers, signIn, signOut } = NextAuth({
  adapter: DrizzleAdapter(db),
  providers: [GitHub],
});

v6 cleaned up the API surface (no more getServerSession boilerplate in Next.js App Router) and improved type inference. For non-Next adapters (SvelteKit, Express, etc.), it works but is less idiomatic than Better Auth in those stacks.

Decision Map

If you...Pick
Are building a single TypeScript app and want batteries-included authBetter Auth
Need passkeys, MFA, and multi-tenant orgs without writing themBetter Auth
Run multiple apps (web + mobile + CLI) that share identityOpenAuth
Are deeply invested in Next.js and want minimal disruptionAuth.js v6
Have an existing NextAuth integrationAuth.js v6 (upgrade, don't migrate)
Want to truly be your own OAuth IdPOpenAuth
Need enterprise SSO (SAML, SCIM)None — see WorkOS / Stytch

Plugin / Feature Comparison

FeatureOpenAuthBetter AuthAuth.js v6
Email + passwordDIYBuilt-inPlugin
Magic linksDIYBuilt-inBuilt-in
Passkeys (WebAuthn)DIYBuilt-inPlugin
TOTP / MFADIYBuilt-inPlugin
Organizations / teamsDIYBuilt-inDIY
Rate limitingDIYBuilt-inDIY
API keysDIYBuilt-inDIY
OAuth client flowsBuilt-in (you ARE the server)Built-inBuilt-in

The "DIY" rows in the OpenAuth column reflect its design — OpenAuth is primarily an OAuth/OIDC server, and feature richness lives at your application layer (which then talks to OpenAuth). Better Auth has the most batteries included.

Database & Adapter Reality

All three support pluggable storage; the practical question is which adapter is best-tested for your DB:

  • Postgres + Drizzle: Better Auth (excellent), Auth.js v6 (good), OpenAuth (DIY).
  • Postgres + Prisma: Better Auth, Auth.js v6 — both good.
  • MongoDB: All three, with varying maturity.
  • Cloudflare D1 / KV: Better Auth has dedicated adapters; OpenAuth is well-suited (since OpenAuth often deploys to Workers).

For broader auth-in-React context, see How to add authentication to a React app.

Migration Notes

  • NextAuth v4 → Auth.js v6: mostly mechanical. Worth doing.
  • NextAuth → Better Auth: requires schema migration and a rewrite of provider config. Worth doing for the plugin features (passkeys, orgs) if you need them.
  • Roll-your-own → Better Auth: usually worth it. Roll-your-own auth in 2026 is hard to justify outside very narrow contexts.
  • Hosted auth → Better Auth: viable if you're escaping per-MAU pricing. Pay attention to the SSO / SCIM gap if your enterprise customers needed it.

Who Should Pick What

  • Solo dev / small team starting fresh: Better Auth. Lowest "I have to make 20 decisions before I have signup working" tax.
  • Existing Next.js app on NextAuth v4: upgrade to Auth.js v6. Don't migrate to Better Auth unless you need plugin features.
  • Org running multiple frontends sharing identity: OpenAuth as the central IdP, Better Auth (or any OAuth client library) inside each app.
  • Enterprise B2B with SAML/SCIM requirements: skip self-hosted; pay for WorkOS or Stytch.
  • Extreme "I want full control" team: roll your own with Lucia v3 or Better Auth and primitives like Oslo or Jose.

Verdict

In 2026, Better Auth is the default-pick for new TypeScript projects that want self-hosted auth — it has caught up with and in many areas surpassed Auth.js v6 for non-Next-specific stacks, and its plugin model handles the rest. Auth.js v6 remains the right answer when you're already on NextAuth and the upgrade path is what you need. OpenAuth is the specialized choice when "auth as its own service" is the architectural decision you've made — usually multi-app organizations that want a real IdP. None of these replace WorkOS-class enterprise auth for SAML/SCIM-driven sales motions.

The 2026 JavaScript Stack Cheatsheet

One PDF: the best package for every category (ORMs, bundlers, auth, testing, state management). Used by 500+ devs. Free, updated monthly.