Skip to main content
Tech Stack progress
intermediatePage 17 of 27

Authentication (Tools)

The auth-as-a-service landscape. Clerk, Better Auth, Auth.js, Auth0, Supabase Auth, WorkOS — and when to pick each.

Authentication (Tools)

In one line: Don't build your own auth. Use Clerk for a polished commercial experience; Better Auth or Auth.js if you want open-source self-hosting; Auth0/WorkOS for enterprise needs.

In plain English

Authentication is hard. Modern best practice is to outsource it — pick a service, drop in their components, focus on your actual product. This page is the landscape of those services.

If you want the conceptual background (sessions vs JWTs, passwords vs passkeys, RBAC vs ABAC), see the Authentication and Authorization pages in chapter 1.

Clerk

Drop-in auth as a service. Pre-built React components.

import { SignIn, SignUp, UserButton } from '@clerk/nextjs';

export default function Page() {
return <SignIn />; // Full sign-in UI in one component
}

Strengths: Best UX, fast to integrate, lots of features (multi-factor, social, magic links, passkeys). Trade-offs: Expensive at scale (~$25/month base, scales by MAU).

Better Auth

Open-source, TypeScript-native, self-hostable. Rising fast in 2026.

import { betterAuth } from 'better-auth';

export const auth = betterAuth({
database: { provider: 'postgres', ... },
emailAndPassword: { enabled: true },
socialProviders: { google: { ... } },
});

Strengths: Free, full control, modern API. Trade-offs: You self-host (more responsibility); newer (less battle-tested than Clerk/Auth0).

Auth.js (formerly NextAuth)

Open-source, framework-integrated. The historical default for Next.js.

Strengths: Free, mature, deep Next.js integration, supports dozens of OAuth providers out of the box. Trade-offs: Less polished DX than Clerk; more boilerplate for custom flows.

Auth0

Mature, enterprise-friendly. Acquired by Okta.

When to use: Enterprise customers, complex compliance requirements, established product.

Supabase Auth

Bundled with Supabase. Convenient if you're already using Supabase for DB.

import { createClient } from '@supabase/supabase-js';
const supabase = createClient(URL, KEY);

await supabase.auth.signInWithPassword({
email: 'tony@x.com',
password: 'secret',
});

WorkOS

Enterprise SSO/SAML/SCIM as a service. The go-to when selling B2B and customers demand enterprise auth.

Decision matrix

NeedRecommendation
Fast time-to-market, paid OKClerk
Open-source, self-hostBetter Auth
Existing Supabase userSupabase Auth
Enterprise B2BClerk + WorkOS, or Auth0
Maximum customizationBuild on Better Auth or Auth.js
Highlight: the auth-service free tiers are real

For solo / startup projects, you almost certainly fit in someone's free tier:

  • Clerk — 10,000 monthly active users free.
  • Supabase Auth — 50,000 monthly active users free.
  • Better Auth — fully free and self-hostable.
  • Auth.js — fully free.

You should not be building your own auth from scratch to "save money." The free tiers are extremely generous and the engineering cost is enormous.

Common mistakes

Where people commonly trip up
  • Rolling your own auth "to save money." The free tiers cover 10k–50k MAU. The engineering hours you save are worth more than the subscription, and you avoid the entire class of session-fixation, timing-attack, and password-hashing bugs.
  • Storing the auth provider's JWT in localStorage. Vulnerable to any XSS bug on your domain. Use httpOnly, Secure, SameSite=Lax cookies (which all these providers default to). If a tutorial tells you to copy a token into localStorage, it's outdated.
  • Treating Clerk as both your auth and your user database. Clerk is the source of truth for identity; your users table is the source of truth for application data. Mirror the Clerk user ID into your DB on first sign-in and join from there — don't try to store orders, preferences, or relationships in Clerk's user metadata.
  • Locking in too early without an export plan. Auth providers are stickier than they look — sessions, password hashes, OAuth connections all live there. Before committing, confirm there's an export API (Clerk, Auth0, Better Auth all have one). If a vendor won't let you leave with your users, that's a flag.
  • Confusing authentication with authorization. The auth provider tells you who the user is. What they're allowed to do (roles, permissions, row-level access) is your app's job. Don't expect Clerk or Auth0 to enforce "this user can edit this document" — you check that on the server, every request.

Page checkpoint

Checkpoint Quiz

Did auth tools stick?

Required

What's next

→ Continue to Background Jobs — long-running and scheduled work that shouldn't block HTTP requests.