Auth.js v5 (the new NextAuth) hit stable in late 2024 as a near-complete rewrite. By September 2025, the Better Auth team had taken over Auth.js maintenance, and the library entered security-patch mode. Meanwhile, Clerk continued shipping features rapidly and now handles everything from MFA to passkeys to B2B organization management out of the box. The authentication landscape shifted significantly in 2025 — here's where each tool stands.
Clerk is a hosted identity platform, not a session library. Your user database, session store, and JWT signing keys live in Clerk's infrastructure. Your app is a client of Clerk's API. This means Clerk handles IP reputation, bot detection, breach password checks, and compliance infrastructure automatically. NextAuth (Auth.js) is the opposite: a session middleware library that you deploy alongside your own database. You own everything — the user table, session tokens, OAuth callback handlers.
Clerk wins on setup speed, decisively. With Clerk, you install the SDK, add middleware, wrap your app in ClerkProvider, and drop in pre-built components like <SignIn /> and <UserButton />. A working auth flow takes under an hour. NextAuth requires configuring adapters, database schemas (users, sessions, accounts tables), choosing and setting up an OAuth provider, and handling session callbacks. For a solo developer or small team with a launch deadline, this difference is significant.
Clerk (Hosted Platform) NextAuth / Auth.js (Self-hosted)
─────────────────────── ────────────────────────────────
Your App Your App
│ │
▼ ▼
ClerkProvider (SDK) auth.ts config (adapters, providers)
│ │
▼ ▼
Clerk API (hosted) Your Database (users/sessions tables)
│ │
├── User store ├── NextAuth JWT / database sessions
├── Session management ├── OAuth callbacks (you handle)
├── MFA / passkeys (included) ├── MFA (build it yourself)
└── Org management └── Token rotation (build it yourself)
Setup time: ~1 hour Setup time: ~4-8 hours
Cost at 50k MAU: $25/month Cost: database + email only
Data location: Clerk's servers Data location: your infrastructure
Compliance: check their ToS Compliance: you control everythingFrom building a SaaS prototype with Clerk: use Clerk's Webhook sync to keep your own database in sync with Clerk's user records. When a user is created or updated in Clerk, the webhook fires and your NestJS or Next.js API handler upserts the record in your PostgreSQL database. This way you can still do relational queries against your own user data without querying Clerk's API on every request.
NextAuth is free — you pay only for your database and email provider. Clerk's pricing starts free (up to 10,000 MAUs) and then scales to $25/month (Pro, billed monthly) for 50,000 Monthly Retained Users. Beyond that, you pay per additional MRU. B2B features — organization management, SSO — are $100/month extra. For a consumer app that hits 50,000 users, Clerk's cost is manageable. For a B2B SaaS with multiple organizations needing SSO, the bill can grow significantly before you've achieved product-market fit.
// Clerk setup (minimal)
// middleware.ts
import { clerkMiddleware } from '@clerk/nextjs/server'
export default clerkMiddleware()
export const config = { matcher: ['/((?!_next|.*\..*).*)'] }
// app/layout.tsx
import { ClerkProvider } from '@clerk/nextjs'
export default function Layout({ children }) {
return <ClerkProvider>{children}</ClerkProvider>
}
// Protected page — done
import { auth } from '@clerk/nextjs/server'
export default async function Dashboard() {
const { userId } = await auth()
if (!userId) redirect('/sign-in')
return <div>Dashboard for {userId}</div>
}
// ─────────────────────────────────────────
// Auth.js v5 (NextAuth) setup
// auth.ts
import NextAuth from "next-auth"
import { PrismaAdapter } from "@auth/prisma-adapter"
import GitHub from "next-auth/providers/github"
import { prisma } from "@/lib/db"
export const { handlers, auth, signIn, signOut } = NextAuth({
adapter: PrismaAdapter(prisma),
providers: [GitHub],
// also need: DATABASE_URL, GITHUB_ID, GITHUB_SECRET, AUTH_SECRET env vars
// also need: prisma schema with User, Account, Session, VerificationToken tables
})Clerk's Pro plan includes MFA (TOTP, SMS), passkeys, 1 enterprise SSO connection, and organization management. NextAuth has no built-in MFA — you implement it yourself with a TOTP library and database columns. Access token rotation, refresh token handling, and bot protection all require manual implementation in NextAuth. If you need these features and don't want to build them, Clerk is the faster path.
Clerk stores user data in the US by default (EU region available on Enterprise plans). For Indonesian or Southeast Asian businesses with data residency requirements, or for any app handling sensitive PII that must stay in-region, Clerk may not be compliant out of the box. NextAuth with your own database gives you full control over data locality. Check your regulatory requirements before choosing a hosted auth provider — this is a decision that's painful to reverse.
Auth.js v5 was a major rewrite — universal runtime support (Edge, Node, Deno), a new unified config in auth.ts, and a cleaner TypeScript API. The adapter pattern improved significantly. However, with the Better Auth team taking over maintenance in late 2025, new Auth.js projects should evaluate Better Auth, which ships with more features and active development. For existing NextAuth v4 projects, v5 migration is well-documented but not urgent.
For client projects where I control the budget and the user count stays under 50k, I use Clerk. The productivity gain during early-stage development is real — I'm not debugging OAuth callbacks when I should be building product features. For open-source projects, internal tools, or any project where I want zero vendor dependency on auth, I use NextAuth/Auth.js with a PostgreSQL adapter. The data ownership matters when I'm building something long-term.
Choose Clerk if: you're building a consumer or B2C SaaS with straightforward auth needs, you value developer velocity, you need MFA and passkeys without custom implementation, and your user count justifies the cost. Choose NextAuth/Auth.js if: you need full data ownership, you have strict data residency requirements, you're building open-source software, or you're on a zero-budget project. The authentication choice is a business decision as much as a technical one — model out the total cost at your expected user scale before committing.