comparison / 05 — updated may 2026

ClerkvsAuth.js

Clerk is auth-as-a-service. Auth.js is auth-as-a-library. The decision is whether you'd rather rent the auth UI or own the integration.

model
Clerkmanaged service
Auth.jsopen-source library
pricing
Clerkfree 10k MAU · $25+ Pro
Auth.jsfree · self-hosted
hosted UI
Clerkyes · prebuilt + customizable
Auth.jsno · build your own
updated
May 2026
verdict.txt — comparisons/clerk-vs-auth-js.mdhonest
$cat verdict.txt

Pick Clerk if your time is worth more than the bill and B2B features (orgs, SSO, multi-tenancy) are on the roadmap. Pick Auth.js if you want to own the auth layer, don't need a hosted UI, and the per-MAU pricing of managed auth doesn't fit your model.

scoreboard / at a glance

At a glance

One row per dimension, the values side-by-side. The olive dot marks the clear winner for that dimension when there is one — most rows are a wash, and that’s the point.

Clerk Inc.

Clerk

Managed auth platform with prebuilt UIs, B2B features (orgs, SSO, RBAC), and Next.js-first integration. You ship a SignIn component, not a system.

Authjs (open source)

Auth.js

Open-source auth library for Next.js (formerly NextAuth.js), now framework-agnostic. OAuth providers, sessions, JWT — you own the database and the UI.

Pricing modelAuth.js is free at any scale. Clerk's per-MAU billing matters once you grow.
free up to 10k MAU · $25/mo Pro · usage above
free · self-hosted · pay for your DB
Time to shipClerk's prebuilt UI removes the 'build a sign-in page' work. Auth.js makes you build it.
30 minutes · install + drop in component
few hours to days · provider config + UI
OAuth providersAuth.js has more provider options. Clerk has fewer but they're polished.
20+ social providers · enterprise SSO on Pro
70+ providers via adapters · SSO via Keycloak/etc
B2B / orgsIf you need multi-tenancy and SSO, Clerk is dramatically less work.
first-class · orgs, RBAC, SSO, invites, domains
DIY · build org schema yourself
Database ownershipAuth.js keeps users in your own database. With Clerk, the canonical user lives at Clerk.
Clerk hosts users · webhook to your DB
your DB · users live in your tables
CustomizationAuth.js gives you more rope. Clerk gives you less rope but better defaults.
themes, components, hosted UI · bounded
complete · you own the entire stack
MFA / passkeysClerk's MFA story is built-in. Auth.js's is bring-your-own.
first-class · TOTP, SMS, passkeys included
passkeys via adapter · TOTP DIY
Session managementClerk's session UX (active devices, revoke, etc.) is polished. Auth.js gives you the primitives.
managed · multi-session, device list, revoke
managed · JWT or DB · revoke is your problem
Lock-inMigrating off Clerk is doable but real. Auth.js has nothing to migrate from.
high · users live at Clerk · export available
low · users in your DB
ComplianceIf you sell to enterprises, Clerk's compliance posture is meaningfully easier than building your own.
SOC 2, GDPR, HIPAA-ready · attestations included
your problem · whatever your DB / hosting provides
pricing / three scenarios

Pricing at three scales

Three receipts, three scales. The line items are the same; the prices move. Every number is from the public May 2026 pricing page — we round to the nearest dollar but don’t invent.

hobby.txt — 0–1k MAU · personal projectmonthly
LINE ITEMClerkAuth.js
Auth platformfree tier · up to 10k MAUfreefree · BYO DBfree
Databasenot needed for usersfreePostgres (Supabase free / Neon)free
TOTAL · monthlyfree/mofree/mo
>Both effectively free at this scale. Clerk's free tier is generous (10k MAU) and includes social login, email/password, and basic MFA. Auth.js is free forever — you're paying for your DB regardless of auth choice.
side project.txt — 10k MAU · paying customers · social + email authmonthly
LINE ITEMClerkAuth.js
Auth platformPro · $25/mo + minimal MAU overage$25freefree
Database for usersusers at Clerk · webhook syncfreeuser table in your Postgresfree
TOTAL · monthly$25/mofree/mo
>At 10k MAU you're at Clerk's Pro tier ($25/mo). Auth.js stays free. Whether $25/mo is worth it depends on how much value you place on prebuilt UI, MFA UX, and session management — for most teams, it is, but the math is real.
scale.txt — 100k MAU · B2B SaaS · orgs + SSO requiredmonthly
LINE ITEMClerkAuth.js
Auth platformPro + 90k MAU overage @ $0.02$1825freefree
B2B add-onsSSO included on ProfreeDIY SSO via Keycloak / WorkOS$99
TOTAL · monthly$1825/mo$99/mo
>At scale Clerk's per-MAU pricing becomes the dominant line item. B2B SaaS with enterprise SSO needs typically pair Auth.js with WorkOS ($99/mo for the SSO middleware). The trade is clear: Clerk costs $20k+/year at 100k MAU; Auth.js costs your engineering time. Many teams decide the engineering time costs more.
features / deep dives

Feature by feature

One row per feature, both tools described in plain language, the honest tradeoff at the bottom. Most rows have legitimate uses for both — the goal is to surface the differences that matter, not to declare a winner on every line.

01

Sign-in components

the actual UI users see
Clerk

Clerk ships React components — <SignIn />, <SignUp />, <UserButton />, <UserProfile /> — that drop into a Next.js app and handle the entire flow. Customization happens through theme variables and per-component props. The default UI is well-designed; teams use it as-is more often than not.

Auth.js

Auth.js gives you the auth logic; the UI is yours to build. You write a sign-in page that calls signIn('google'), handle the callback, render the session state. The provider-recipe docs are excellent, but you're the one writing JSX.

Honest tradeoff

Clerk saves you several days of UI work and gets you a polished result by default. Auth.js makes you do the work but lets you build exactly the UI you want. For consumer products with strong brand requirements, you may end up rebuilding what Clerk already gave you anyway.

02

User management

where users live and how you query them
Clerk

With Clerk, users live in Clerk's database. You query them via Clerk's API or webhook them into your own DB on signup/update for relational queries. The dashboard handles user search, edit, ban, soft-delete. Most apps end up with both — canonical users at Clerk, denormalized copies in their DB for joins.

Auth.js

With Auth.js, users live in your database from day one. The default Postgres adapter creates users, accounts, sessions, verification_tokens tables. You write the JOIN, you own the schema. Want to add a 'subscribed' boolean to the user? You add a column.

Honest tradeoff

Auth.js's database ownership is genuinely simpler if your app is data-heavy and users need to JOIN against your business tables. Clerk's two-system model (canonical at Clerk, mirror in your DB) works but is one more sync to maintain.

03

B2B / multi-tenancy

organizations, roles, SSO
Clerk

Clerk's B2B features are first-class: organizations, role-based access control, organization invitations, SAML SSO (on Pro+), domain-based auto-join, organization switcher UI. The mental model matches B2B SaaS conventions; the components are drop-in.

Auth.js

Auth.js doesn't have B2B features built in. You'd build the org table, the org_members join table, the role enum, the invitation flow, and the SSO integration yourself (often via WorkOS or Keycloak as the SSO middleware). It's all standard work, but it's all yours to do.

Honest tradeoff

If you're building B2B SaaS and orgs/SSO are on the roadmap, Clerk saves weeks of work and you get a UI that matches B2B conventions. Auth.js is a meaningful undertaking for the same feature set.

04

MFA & passkeys

second-factor and passwordless
Clerk

Clerk ships TOTP, SMS, email codes, backup codes, and WebAuthn passkeys as built-in flows. The UI prompts users to enroll, manages backup codes, handles recovery. You toggle MFA requirements per-app or per-org.

Auth.js

Auth.js supports passkeys via the WebAuthn adapter. TOTP and SMS MFA are not built-in — you wire up your own (using libraries like otplib for TOTP, Twilio for SMS) and store the factor data in your DB.

Honest tradeoff

If MFA is required (compliance, B2B) or just nice-to-have (consumer), Clerk's built-in story is dramatically less work. Auth.js's MFA is a significant feature to build and maintain.

05

Session management

JWT vs session cookies, revocation, devices
Clerk

Clerk uses session tokens by default with active-session tracking. Users see a 'Devices' list in their profile and can revoke individual sessions. Tokens are short-lived; refresh happens transparently. Multi-tab session sync just works.

Auth.js

Auth.js supports both JWT (stateless) and database sessions. JWT is simpler but doesn't allow revocation; database sessions allow revocation but require a DB lookup per request. The choice is a real architectural decision you'll make and live with.

Honest tradeoff

Clerk hides the JWT-vs-session tradeoff and gives you revoke-and-track for free. Auth.js exposes the tradeoff and asks you to pick — appropriate for libraries, more friction for product builders.

06

OAuth provider coverage

the buttons users actually click
Clerk

Clerk supports 20+ social providers (Google, GitHub, Microsoft, Apple, Discord, Twitch, Facebook, etc.). Custom OIDC providers are supported on Pro. Enterprise SSO (SAML) is a Pro feature; it works with Okta, Azure AD, Google Workspace, Auth0, etc.

Auth.js

Auth.js supports 70+ providers out of the box, plus a generic OAuth/OIDC adapter for anything not in the list. Enterprise SSO comes via adding Keycloak or WorkOS as a provider; Auth.js doesn't speak SAML directly.

Honest tradeoff

Auth.js wins on raw provider count. Clerk has fewer but covers the providers most apps actually use; the long tail rarely matters in practice.

07

Webhooks & integrations

syncing auth events to your stack
Clerk

Clerk emits webhooks for user.created, user.updated, session.created, session.ended, organization.created, etc. Signing via Svix. The webhook payload is well-documented and the dashboard has a replay tool. Most apps use webhooks to mirror users into their own DB.

Auth.js

Auth.js has callback hooks (signIn, jwt, session) that run inline during auth flows — you mutate the session payload, write to your DB, decline a sign-in. There's no async webhook system because the events happen in your own code.

Honest tradeoff

Clerk's webhooks are the right model for 'auth happens at Clerk, propagate to my system.' Auth.js's callbacks are the right model for 'auth happens in my system, hook directly into the flow.' Match to your architecture.

08

Migration & exit

what it takes to leave
Clerk

Migrating off Clerk involves: exporting users (CSV or API), importing into a new auth system, having every user re-authenticate (password hashes are not portable across systems), and deciding what to do with active sessions (force re-login or accept the rotation). It's a real project — typically 1–3 weeks plus customer comms.

Auth.js

Auth.js has nothing to migrate from — your users are in your database. If you decide to switch to Clerk later, the same migration applies in reverse. The 'staying in Auth.js' path is just changes to your own code.

Honest tradeoff

Clerk's lock-in is real and worth pricing in. Auth.js has effectively no lock-in. If you expect to be acquired or to consolidate auth across multiple products, the portability matters.

verdict / pick one

When to pick which

pick / clerk

Pick Clerk if…

  • You're shipping a B2B SaaS and orgs / SSO / multi-tenancy are on the roadmap.
  • Your team's time is worth more than the per-MAU pricing — you'd rather pay than build.
  • MFA, passkeys, and active-session management are required (security or compliance).
  • You want a polished UI on day one without designing or building it.
  • Compliance posture (SOC 2, GDPR, HIPAA) matters and you'd rather inherit Clerk's.
pick / auth.js

Pick Auth.js if…

  • Auth is a load-bearing part of your app and you want to own the database, schema, and UI.
  • Per-MAU pricing doesn't fit your business model — high-volume free users, for instance.
  • Your auth needs are conventional (social + email) and you don't need B2B / SSO features.
  • You're philosophically uncomfortable with users-as-a-service for your core product.
  • Engineering time is cheaper for you than $1k+/mo at scale — typical for early-stage and indie.
gotchas / observed

Gotchas, both directions

Common pitfalls visible in public docs and community discussion. None of these will stop you shipping; all of them will cost you an afternoon if you don’t know about them.

  • Clerk / pricing

    Per-MAU billing scales aggressively past 10k

    The free 10k MAU tier is generous, but each MAU above costs ~$0.02. A consumer app at 100k MAU pays ~$1,800/mo just for auth. The math becomes a real architecture decision around 50k+ MAU; budget for it before you grow.

  • Auth.js / sessions

    JWT sessions can't be revoked

    If you choose JWT (the simpler default), you can't immediately revoke a stolen token — only invalidate by waiting for the JWT to expire. For high-security apps, use database sessions instead and accept the per-request DB lookup. The decision is one-way and worth making consciously.

  • Clerk / lock-in

    Password hashes are not portable

    Clerk uses Argon2 with a per-instance salt. If you migrate off, your existing users will have to reset their passwords on first login at the new system. Plan a customer-comms moment around the migration.

  • Auth.js / TypeScript

    The session type is loose by default

    Auth.js's Session type defaults to a generic shape that doesn't include your custom fields. You augment via module declaration in next-auth.d.ts (or similar) — easy to forget; bites you when an `any` slips through and you ship a bug. Set up the augmentation on day one.

  • Clerk / webhooks

    Webhook ordering is not guaranteed

    If a user signs up and immediately updates their profile, you may receive user.updated before user.created. Idempotent handlers are required, not optional — store the latest version of each user state regardless of webhook order.

  • Auth.js / production

    AUTH_SECRET is required in production but not in dev

    In dev, Auth.js generates a random AUTH_SECRET on the fly. In production, you must set one — and a missing AUTH_SECRET produces a generic 500, not a clear error. The first production deploy fails this way more often than it should. Set the env var before you deploy, not after.

migration / observed patterns

Migrating between them

Editorial framing only — we have not migrated either way ourselves. What follows is the pattern visible in public post-mortems, GitHub issue threads, and conference talks. Take it as observed-pattern, not lived experience.

Auth.js ━▶ Clerk

Common pattern: a startup hits product-market-fit, growth accelerates, and the engineering bandwidth to build org/SSO/MFA suddenly looks expensive. They migrate to Clerk for the bundle. Mechanically: export users from your DB, batch-import to Clerk via the API (passwords reset on first login), update the app to use Clerk's components, run both systems in parallel for a transition period.

The hard part isn't the data — it's the UX shift. Users encountering a 'reset your password' flow on first login is a customer-comms moment. Some teams stage the migration over weeks (let cards naturally re-auth on session expiry rather than forcing).

Clerk ━▶ Auth.js

Less common but happens at scale — a company at 100k+ MAU realizes the per-MAU bill is funding a Clerk-shaped business they don't strictly need. Migration is a Clerk user export, Auth.js setup with the user table mirroring Clerk's schema, and a forced password-reset on first login (because hashes don't port). Plan 3–6 weeks for a clean migration with proper user comms.

The trigger is rarely just price — it's usually a combination of price, lock-in concerns, and a desire to consolidate the auth layer with the rest of the database. Some teams do it during a planned auth refresh anyway (passkey rollout, SSO support).