All insights
Engineering9 min read

Authentication in Next.js: NextAuth vs Clerk vs Supabase Auth

Authentication is one of the first decisions you make in a new project and one of the hardest to change later. Here's how the three leading options compare in a production Next.js context.

NC

Nextcraft Engineering Team

Why Auth Choice Matters More Than You Think

Authentication touches every layer of your stack: middleware, server components, API routes, client state. Choosing the wrong solution means either ripping it out six months in, or living with architectural debt that makes every new feature harder.

We've shipped production apps with all three of the major Next.js auth solutions. Here's what actually matters.

NextAuth.js (Auth.js v5)

Best for: Custom auth flows, multiple OAuth providers, self-hosted requirements.

NextAuth v5 (now branded Auth.js) was rebuilt for the App Router. The API is cleaner than v4 and integrates naturally with Server Components and middleware.

code
// auth.ts
import NextAuth from 'next-auth';
import GitHub from 'next-auth/providers/github';

export const { handlers, signIn, signOut, auth } = NextAuth({
  providers: [GitHub],
  callbacks: {
    authorized({ auth, request }) {
      return !!auth?.user; // Protect routes in middleware
    },
  },
});
code
// In a Server Component
import { auth } from '@/auth';

export default async function Dashboard() {
  const session = await auth();
  if (!session) redirect('/login');
  return <DashboardContent user={session.user} />;
}

Strengths:

  • Free and self-hosted — no per-MAU costs
  • Highly configurable: custom session strategies, JWT handling, database adapters
  • 40+ OAuth providers built in
  • Strong community, mature codebase

Weaknesses:

  • You manage the complexity: email templates, password reset flows, MFA all require custom implementation
  • Database setup required for session persistence
  • No built-in UI components — you build your own sign-in pages
  • Debugging session issues can be painful

Verdict: Best for teams comfortable with backend work who want zero vendor lock-in and full control.

Clerk

Best for: Rapid development, teams that want auth solved completely.

Clerk provides hosted authentication with pre-built UI components, a full user management dashboard, and an SDK that integrates deeply with Next.js App Router patterns.

code
// middleware.ts
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';

const isProtectedRoute = createRouteMatcher(['/dashboard(.*)']);

export default clerkMiddleware((auth, req) => {
  if (isProtectedRoute(req)) auth().protect();
});
code
// In a Server Component
import { currentUser } from '@clerk/nextjs/server';

export default async function Profile() {
  const user = await currentUser();
  return <div>Hello {user?.firstName}</div>;
}

Strengths:

  • Complete solution: sign-up, sign-in, MFA, SSO, user profiles, org management
  • Pre-built, customizable UI components that look professional out of the box
  • Excellent Next.js middleware integration — route protection in 5 lines
  • Works edge-side in middleware without database queries
  • Webhooks for user events

Weaknesses:

  • Costs money at scale ($0.02/MAU after free tier)
  • Less control over session logic
  • Your users' auth data lives on Clerk's infrastructure
  • Customization beyond their theming system requires workarounds

Verdict: Best for SaaS products where shipping fast matters more than minimizing vendor dependencies. The time saved on auth is significant.

Supabase Auth

Best for: Teams already using Supabase for their database.

Supabase Auth is built on GoTrue and integrates tightly with Supabase's Row Level Security (RLS) system. If you're using Supabase as your database, using anything else for auth means giving up the RLS integration — which is a significant loss.

code
// Create a Supabase server client
import { createServerClient } from '@supabase/ssr';
import { cookies } from 'next/headers';

export function createClient() {
  const cookieStore = cookies();
  return createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    { cookies: { getAll: () => cookieStore.getAll() } }
  );
}

// In a Server Component
export default async function Page() {
  const supabase = createClient();
  const { data: { user } } = await supabase.auth.getUser();
  if (!user) redirect('/login');
  
  // RLS automatically filters data to the current user
  const { data: posts } = await supabase.from('posts').select();
  return <PostList posts={posts} />;
}

Strengths:

  • RLS integration is genuinely powerful — database-level security without custom query filters
  • Free tier is generous
  • Built-in email/password, OAuth, magic links, phone auth
  • Self-hostable with Docker

Weaknesses:

  • Cookie management with App Router requires careful setup (the @supabase/ssr package)
  • Less polished middleware integration than Clerk
  • Organization/team management not built in
  • Weaker TypeScript DX than the alternatives

Verdict: The obvious choice if Supabase is your database. Otherwise, only worth it if you specifically want self-hosted and free.

The Decision Matrix

CriteriaNextAuthClerkSupabase Auth
Cost at scaleFree$0.02/MAUFree/self-hosted
Setup timeDaysHoursHours
CustomizationMaximumModerateModerate
Built-in UINoneFullBasic
MFADIYBuilt-inBuilt-in
Org managementDIYBuilt-inLimited
Database integrationVia adaptersWebhooksNative (Supabase)
Self-hostedYesNoYes

Our Recommendation

  • Bootstrapped SaaS / side project: Clerk — ship faster, worry about it later
  • Enterprise / compliance requirements: NextAuth with a custom database adapter
  • Using Supabase database: Supabase Auth, no question
  • High scale, cost-sensitive: NextAuth or self-hosted Supabase

The wrong choice isn't catastrophic. Migrating auth is painful but not impossible. But getting it right upfront saves you a week of migration work at the worst possible moment — usually right before a launch.

Stay Informed.

Join 1,200+ founders and engineers receiving our monthly deep dives on product engineering, design, and growth.

Insights once a month. No spam. Unsubscribe anytime.