Clerk vs NextAuth in 2026: Managed vs Self-Hosted Auth
·PkgPulse Team
TL;DR
Clerk if you want to ship auth in 30 minutes; NextAuth if you need full control or can't justify the cost. Clerk (~1M weekly downloads) is a managed auth service with beautiful pre-built UI, social sign-in, MFA, and organizations out of the box. NextAuth/Auth.js (~2.5M downloads) is free, self-hosted, and highly customizable. Clerk's pricing starts free but scales to $25/month for 10,000 MAU. NextAuth is always free.
Key Takeaways
- NextAuth/Auth.js: ~2.5M weekly downloads — Clerk: ~1M (npm, March 2026)
- Clerk is fully managed — no database tables needed for auth
- Clerk pricing: free → $25+/month at scale — NextAuth is always free
- Clerk has built-in UI — embeddable sign-in/sign-up components
- NextAuth supports 80+ OAuth providers — Clerk supports major ones
Setup Comparison
// NextAuth (Auth.js) — self-hosted, needs database adapter
// app/api/auth/[...nextauth]/route.ts
import NextAuth from 'next-auth';
import GitHub from 'next-auth/providers/github';
import Google from 'next-auth/providers/google';
import { DrizzleAdapter } from '@auth/drizzle-adapter';
import { db } from '@/db';
export const { handlers, auth, signIn, signOut } = NextAuth({
adapter: DrizzleAdapter(db), // Stores sessions in your database
providers: [
GitHub({
clientId: process.env.GITHUB_ID!,
clientSecret: process.env.GITHUB_SECRET!,
}),
Google({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
}),
],
callbacks: {
session({ session, user }) {
session.user.id = user.id; // Add user ID to session
return session;
},
},
});
// You must:
// 1. Set up database tables (via adapter migration)
// 2. Configure OAuth apps in GitHub/Google
// 3. Handle session state yourself
// Clerk — minimal setup, managed service
// app/layout.tsx
import { ClerkProvider } from '@clerk/nextjs';
export default function RootLayout({ children }) {
return (
<ClerkProvider>
<html><body>{children}</body></html>
</ClerkProvider>
);
}
// middleware.ts — protect routes
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';
const isProtected = createRouteMatcher(['/dashboard(.*)']);
export default clerkMiddleware((auth, req) => {
if (isProtected(req)) auth().protect();
});
// That's it — Clerk manages users, sessions, and auth state
// No database setup required for auth
UI Components
// Clerk — beautiful pre-built components (Drop-in UI)
import { SignIn, SignUp, UserButton, UserProfile } from '@clerk/nextjs';
// Full sign-in page in one component:
export default function SignInPage() {
return <SignIn />;
// Includes: email/password, social login, MFA prompt
// Fully styled, customizable via Clerk dashboard theme
}
// User avatar + dropdown (profile, settings, sign out):
function Nav() {
return (
<nav>
<Logo />
<UserButton afterSignOutUrl="/" />
</nav>
);
}
// NextAuth — you build the UI yourself
'use client';
import { signIn, signOut, useSession } from 'next-auth/react';
function SignInPage() {
return (
<div>
<button onClick={() => signIn('github')}>Sign in with GitHub</button>
<button onClick={() => signIn('google')}>Sign in with Google</button>
{/* Build your own UI */}
</div>
);
}
function Nav() {
const { data: session } = useSession();
return (
<nav>
<Logo />
{session ? (
<button onClick={() => signOut()}>Sign out ({session.user?.name})</button>
) : (
<button onClick={() => signIn()}>Sign in</button>
)}
</nav>
);
}
Organizations / Multi-Tenancy
// Clerk — organizations built in
import { useOrganization, useOrganizationList } from '@clerk/nextjs';
function OrgSwitcher() {
const { organization } = useOrganization();
const { setActive, organizationList } = useOrganizationList();
return (
<select onChange={(e) => setActive({ organization: e.target.value })}>
{organizationList?.map(({ organization: org }) => (
<option key={org.id} value={org.id}>{org.name}</option>
))}
</select>
);
}
// Clerk handles: invitations, member roles, org switching
// Cost: requires Pro plan ($25+/month)
// NextAuth — implement organizations yourself
// NextAuth has no concept of organizations — build it from scratch:
// - organizations table in your database
// - membership table with roles
// - org context in session
// - invitation system
// Typically 2-4 weeks of work
Pricing Reality
Clerk pricing (March 2026):
Free: 10,000 MAU
Pro: $25/month base + $0.02 per MAU over 10K
B2B (Organizations): included in Pro
For 50,000 MAU: $25 + (40,000 × $0.02) = $825/month
NextAuth (Auth.js):
Always free — you pay for your own database hosting
For 50,000 MAU: $0 (+ whatever your Vercel/PlanetScale costs)
At scale, Clerk's cost advantage disappears. At startup scale (<10K MAU), it's free.
When to Choose
Choose Clerk when:
- Speed to ship is paramount (auth in 30 minutes)
- You need organizations/multi-tenancy without building from scratch
- Your app needs MFA, device sessions, or enterprise SSO
- <10,000 MAU (free tier)
- You value the hosted management dashboard
Choose NextAuth/Auth.js when:
- Cost control is important at scale
- You need full control over the auth flow
- Custom auth logic that Clerk's managed service can't accommodate
- GDPR/compliance requirements that prevent sending user data to third parties
-
10,000 MAU and cost is a concern
Compare Clerk and NextAuth package health on PkgPulse.
See the live comparison
View clerk vs. nextauth on PkgPulse →