Lompat ke konten utama
vourdev
Kembali ke Blog

Dev Notes

NextAuth vs Clerk vs Supabase Auth: Pilih yang Mana Buat Aplikasi Lu?

Bedah tuntas perbandingan NextAuth, Clerk, dan Supabase Auth dari sisi arsitektur, DX, skema data, hingga biaya di skala produksi.

Gambar Cover NextAuth vs Clerk vs Supabase Auth: Pilih yang Mana Buat Aplikasi Lu?
Ditulis olehvourdev12 menit baca

Bikin sistem autentikasi sendiri di tahun 2024 itu bentuk masokisme teknis yang gak perlu. Dulu kita harus pusing mikirin hash password pakai Argon2/Bcrypt, ngatur session cookie HttpOnly & SameSite, cegah CSRF, sampai bikin flow reset password via email.

Sekarang, problem-nya berbalik: terlalu banyak pilihan platform Auth.

Tiga opsi paling dominan di ekosistem JavaScript/TypeScript saat ini adalah NextAuth.js (Auth.js), Clerk, dan Supabase Auth. Ketiganya kelihatan mirip di permukaan—sama-sama bisa bikin user login lewat Google atau email-password dalam hitungan menit. Tapi begitu aplikasi lu mulai scale, butuh custom metadata, atau masuk ke requirement enterprise seperti B2B Organization Management, perbedaan arsitektur ketiga tools ini bakal kerasa banget.

Salah pilih solusi Auth di awal bisa bikin lu kejebak di dua lubang buaya: Vendor Lock-in berbiaya mahal atau Technical Debt refactoring berbulan-bulan.

Di artikel ini, kita bakal bedah ketiganya secara teknis: dari arsitektur penyimpanan session, cara kerja middleware, penanganan data user, sampai perbandingan biaya nyata saat MAU (Monthly Active Users) lu meledak.

Arsitektur Dasar NextAuth vs Clerk vs Supabase AuthNextAuth.js (Auth.js)Self-hosted / In-AppDatabase milik sendirivia AdapterFull Custom UISession di JWT / LocalDBClerkFully Managed SaaSUser Data di serverClerkPre-built UIComponentsSession di Clerk EdgeInfrastructureSupabase AuthIntegrated BaaS(PostgreSQL)User Data di schemaauth.usersUI via Helper / CustomIntegrasi bawaan RLS& Triggers
Arsitektur Dasar NextAuth vs Clerk vs Supabase Auth

1. Developer Experience (DX) & Kecepatan Integrasi

Implementasi koding autentikasi pada Next.js
Konfigurasi autentikasi require balance antara kemudahan integrasi dan fleksibilitas data. · Florian Olivo (Unsplash)

Developer experience bukan sekadar seberapa cepat lu dapet tombol "Login with Google", tapi seberapa sedikit boilerplate code yang harus lu rawat di masa depan.

NextAuth.js (Auth.js): Fleksibel, tapi Rentan Breaking Changes

NextAuth (sekarang bertransisi ke Auth.js v5) adalah standar de-facto kalau lu mau full control tanpa bergantung pada layanan SaaS pihak ketiga. Lu cuma perlu pasang adapter database (seperti Prisma atau Drizzle), konfigurasikan provider, dan lu dapet handler API otomatis.

Namun, pengalamannya gak selalu mulus. Transisi dari Next.js Pages Router ke App Router sempat memicu breaking changes yang cukup masif di NextAuth v4 ke v5.

typescript
// auth.ts (Auth.js v5 Beta / NextAuth)
import NextAuth from "next-auth"
import Google from "next-auth/providers/google"
import { PrismaAdapter } from "@auth/prisma-adapter"
import { prisma } from "@/lib/prisma"

export const { handlers, auth, signIn, signOut } = NextAuth({
  adapter: PrismaAdapter(prisma),
  providers: [
    Google({
      clientId: process.env.AUTH_GOOGLE_ID,
      clientSecret: process.env.AUTH_GOOGLE_SECRET,
    }),
  ],
  callbacks: {
    async session({ session, user }) {
      // Wajib inject user ID manual ke session kalau butuh ID di client
      if (session.user) {
        session.user.id = user.id;
      }
      return session;
    },
  },
})

Kelebihan NextAuth: Lu gak perlu bayar sepeser pun ke pihak ketiga. Semua session dan account tersimpan di database lu sendiri.

Kekurangan: UI harus bikin sendiri dari nol. Lu bertanggung jawab penuh atas manajemen session, error handling OAuth callback, dan compatibility issue saat Next.js rilis major version baru.

Clerk: Rajanya DX & Pre-built Component

Clerk mengambil pendekatan plug-and-play. Mereka gak cuma nyediain API, tapi juga komponen React siap pakai seperti <SignIn />, <UserProfile />, dan <OrganizationSwitcher /> yang styling-nya bisa disesuaikan pakai Tailwind CSS.

typescript
// middleware.ts (Clerk Auth Protection)
import { clerkMiddleware, createRouteMatcher } from "@clerk/nextjs/server";

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

export default clerkMiddleware((auth, req) => {
  if (isProtectedRoute(req)) {
    auth().protect();
  }
});

export const config = {
  matcher: ['/((?!.*\\..*|_next).*)', '/', '/(api|trpc)(.*)'],
};

Dengan konfigurasi middleware super simpel di atas, seluruh route di dalam /dashboard langsung terlindungi. Lu dapet UI modal login, avatar dropdown, manajemen multi-session, hingga 2FA (Two-Factor Authentication) tanpa nulis kode backend tambahan.

Supabase Auth: Senjata Utama Ekosistem Postgres

Kalau lu udah pakai Supabase sebagai database utama, pakai Supabase Auth itu no-brainer. Supabase Auth terintegrasi langsung dengan fitur utama PostgreSQL: Row Level Security (RLS).

typescript
// lib/supabase/server.ts
import { createServerClient } from '@supabase/ssr'
import { cookies } from 'headers'

export async function createClient() {
  const cookieStore = await cookies()

  return createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: {
        getAll() {
          return cookieStore.getAll()
        },
        setAll(cookiesToSet) {
          try {
            cookiesToSet.forEach(({ name, value, options }) =>
              cookieStore.set(name, value, options)
            )
          } catch {
            // Called from Server Components
          }
        },
      },
    }
  )
}

Supabase menyediakan package @supabase/ssr yang menangani enkripsi cookie secara otomatis di Server Components, Client Components, dan Server Actions pada Next.js.


2. Manajemen Data User & Strategi Storage

Tampilan visual struktur database dan tabel user
Model penyimpanan data user menentukan seberapa mudah lu melakukan relational query. · Rahul Mishra (Unsplash)

Pertanyaan paling krusial pas milih Auth provider: "Di mana data user gue disimpan, dan seberapa gampang gue join data user dengan data bisnis?"

Alur Pengambilan Data User: Webhook Sync vs Direct Postgres JoinClient RequestFetch User ProfileClerk WebhookSync to Local DBLocal DatabaseApp DatabaseSupabase Postgresauth.users + public.profilesAuth via ClerkAsync HTTP EventDirect SQL Join / RLS
Alur Pengambilan Data User: Webhook Sync vs Direct Postgres Join

NextAuth: Data Terpusat di DB Utama

Karena pakai Adapter (Prisma/Drizzle/TypeORM), tabel User, Account, Session, dan VerificationToken hidup langsung di database aplikasi lu.

  • Plus: Lu bisa bikin query JOIN langsung antara tabel User dengan tabel Order, Post, atau Subscription tanpa latency jaringan tambahan.
  • Minus: Database lu ikut menampung beban I/O session. Kalau pakai strategy session database alih-alih jwt, setiap request bakal ngelakuin hit read ke DB.

Clerk: Data Terpisah di Vault Vendor

Clerk menyimpan seluruh data identitas user di infrastruktur mereka sendiri. Kalau aplikasi lu butuh relasi database (misal: "Tampilkan 10 transaksi terakhir dari User X"), lu punya dua opsi:

  1. Simpan Clerk User ID (`user_2N...`) sebagai Foreign Key di DB lokal lu. Saat butuh detail nama/email, query API Clerk atau bawa dari Session Token.
  2. Sinkronisasi via Webhook: Bikin webhook endpoint untuk mendengarkan event user.created dan user.updated dari Clerk, lalu simpan salinan datanya ke DB lokal.
Gotcha Clerk Webhook: Lu harus menangani kasus di mana webhook delay atau failed delivery. Jangan sampai user sukses signup di Clerk, tapi begitu di-redirect ke dashboard, data user-nya belum terbuat di database lokal lu karena webhook-nya telat 200ms.

Supabase Auth: Skema auth.users dan Magic SQL Trigger

Supabase menyimpan data auth di schema terpisah bernama auth.users. Data ini terisolasi demi keamanan, tapi karena masih di dalam PostgreSQL yang sama, lu bisa bikin relasi ke schema public menggunakan SQL Trigger.

sql
-- Membikin tabel profiles di schema public
CREATE TABLE public.profiles (
  id UUID REFERENCES auth.users ON DELETE CASCADE PRIMARY KEY,
  full_name TEXT,
  avatar_url TEXT,
  updated_at TIMESTAMP WITH TIME ZONE
);

-- Bikin function trigger untuk sinkronisasi otomatis dari auth.users ke public.profiles
CREATE OR REPLACE FUNCTION public.handle_new_user()
RETURNS TRIGGER AS $$
BEGIN
  INSERT INTO public.profiles (id, full_name, avatar_url)
  VALUES (new.id, new.raw_user_meta_data->>'full_name', new.raw_user_meta_data->>'avatar_url');
  RETURN NEW;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- Trigger eksekusi setiap ada user baru mendaftar
CREATE TRIGGER on_auth_user_created
  AFTER INSERT ON auth.users
  FOR EACH ROW EXECUTE FUNCTION public.handle_new_user();

Dengan pola di atas, setiap ada pendaftaran user baru via Supabase Auth (OAuth/Email), PostgreSQL akan menyalin datanya ke public.profiles secara atomic (dalam satu transaksi database). Tidak ada potensi race condition seperti pada webhook HTTP!


3. Keamanan & Row Level Security (RLS)

Keamanan autentikasi gak cuma berhenti di login page, tapi gimana data lu dilindungi di tingkat database.

Sekuens Otorisasi Request via Supabase RLSBrowserNext.js Server / APISupabase Postgres1. 1. Send Request + JWT Cookie2. 2. Query with auth.uid()3. 3. Filter rows based on RLS Pol…
Sekuens Otorisasi Request via Supabase RLS

Dampak RLS pada Supabase

Supabase memanfaatkan JWT yang dikirim di setiap request header untuk mengidentifikasi auth.uid() langsung dari dalam engine PostgreSQL. Lu gak perlu nulis pengecekan otorisasi manual di backend code untuk setiap query.

sql
-- Kebijakan RLS: User cuma bisa baca dan update data milik mereka sendiri
ALTER TABLE public.posts ENABLE ROW LEVEL SECURITY;

CREATE POLICY "User can update their own posts" 
ON public.posts 
FOR UPDATE 
USING (auth.uid() = user_id);

Kalau hacker mencoba membobol API lu dan melakukan query tanpa user ID yang valid, engine PostgreSQL sendiri yang akan menolak query tersebut, bahkan sebelum API handler lu selesai mengeksekusi kode.

Security di NextAuth & Clerk

Di NextAuth dan Clerk, otorisasi dilakukan di application level (middleware / API route). Lu harus mengecek session secara manual di setiap Server Action atau Route Handler:

typescript
// Contoh otorisasi manual di Next.js App Router (Clerk)
import { auth } from "@clerk/nextjs/server";

export async function DELETE(request: Request, { params }: { params: { id: string } }) {
  const { userId } = auth();
  
  if (!userId) {
    return new Response("Unauthorized", { status: 401 });
  }

  // Lu wajib manual pastikan item ini milik userId tersebut di DB query!
  const post = await db.post.findUnique({ where: { id: params.id } });
  if (post?.authorId !== userId) {
    return new Response("Forbidden", { status: 403 });
  }

  await db.post.delete({ where: { id: params.id } });
  return new Response("Deleted", { status: 200 });
}

Pola ini sepenuhnya aman, tapi punya resiko human error: kalau lu lupa nambahin check if (post?.authorId !== userId) di salah satu endpoint, aplikasi lu berpotensi kena celah keamanan IDOR (Insecure Direct Object References).


4. Analisis Biaya & Scaling (Pricing Tier)

Ini bagian yang paling sering bikin founder atau Tech Lead kaget pas aplikasi mulai dapet traction. Strategi pricing ketiga tools ini beda banget.

Tumpukan Biaya & Kompleksitas PemeliharaanClerk: Free s/d 10k MAU, lalu Pay-as-you-go per MAU + Add-ons B2Supabase Auth: $25/mo Pro Plan (Free 50k MAU, scale-up murah)NextAuth.js: $0/mo SaaS Fee (Biaya: Maintenance Infra & DB I/O s
Tumpukan Biaya & Kompleksitas Pemeliharaan

Summary Perhitungan Simulasi Biaya

Mari kita hitung estimasi biaya bulanan berdasarkan jumlah Monthly Active Users (MAU):

| MAU (Monthly Active User) | NextAuth.js | Clerk (Pro Plan) | Supabase Auth (Pro Plan) |

| :--- | :--- | :--- | :--- |

| 1.000 MAU | $0 (Free) | $0 (Free Tier s.d. 10k) | $0 (Free Tier s.d. 50k) |

| 20.000 MAU | $0 (Free) | ~$250 - $500 / bulan | $25 / bulan |

| 100.000 MAU | $0 (Free) | ~$2.000+ / bulan | ~$100 / bulan (Overages) |

Catatan Biaya Clerk: Clerk memang punya Free Tier yang sangat murah hati (up to 10,000 MAU). Tapi setelah melewati batas free, penambahannya dinilai per active user + biaya fitur tambahan seperti Custom Domain ($10/bln), SAML Single Sign-On (SSO) yang bisa mencapai $500+/bulan untuk fitur B2B SaaS.
Catatan Biaya NextAuth: Biaya lisensi software NextAuth memang $0. Tapi ingat, "Free as in freedom, not as in free beer". Lu tetap bayar biaya CPU/Database untuk menangani session read/write dan waktu engineering cost tim lu buat maintain auth code.

5. Decision Matrix: Pilih yang Mana Buat Project Lu?

Biar gak bingung, ini cheat sheet ringkas berdasarkan jenis project yang sedang lu bangun:

Panduan Evolusi & Pemilihan Stack AuthFase MVP Cepat /B2B SaaSPilih Clerk (Speed > Cost)Fase Data-Heavy /Full Stack PostgresPilih Supabase Auth (RLS &Ecosystem)Fase Self-Hosted /Enterprise OwnershipPilih NextAuth / Auth.js(Zero Lock-in)
Panduan Evolusi & Pemilihan Stack Auth

1. Gunakan Clerk jika:

  • Lu lagi ngebangun B2B SaaS, butuh fitur Multi-tenancy, Organization Management, Invite Member, dan Role-Based Access Control (RBAC) instan.
  • Lu mau launching MVP sesegera mungkin dan gak mau pusing bikin UI login, modal 2FA, atau setting reset password email.
  • Lu punya budget / runway finansial yang cukup untuk membayar biaya per-MAU begitu aplikasi scale up.

2. Gunakan Supabase Auth jika:

  • Lu menggunakan PostgreSQL (terutama Supabase) sebagai database utama aplikasi.
  • Lu ingin memanfaatkan keamanan tingkat database menggunakan Postgres Row Level Security (RLS).
  • Lu butuh autentikasi yang cost-effective untuk aplikasi B2C yang targetnya puluhan ribu hingga ratusan ribu user aktif.

3. Gunakan NextAuth.js (Auth.js) jika:

  • Lu menginginkan 100% Data Ownership—semua credential dan session user wajib berada di database lokal milik sendiri.
  • Lu pengen zero-vendor lock-in dan budget software $0.
  • Lu sudah punya sistem UI component kit sendiri dan nyaman ngatur flow token/session secara manual di Next.js App Router.

Kesimpulan & Action Items

Gak ada jawaban tunggal "tool mana yang paling bagus". Pilihan terbaik selalu tergantung pada trade-off antara Kecepatan Development (DX), Kontrol Infrastruktur, dan Biaya Jangka Panjang.

Langkah Konkret Sekarang:

  1. Evaluasi DB Utama: Kalau DB lu udah Postgres di Supabase, jangan muter-muter—langsung pakai Supabase Auth.
  2. Hitung Projection Users: Jika lu bikin app B2C dengan jutaan user gratisan, hindari provider dengan skema pricing MAU yang mahal seperti Clerk, atau batasi penggunaannya. Pilih NextAuth atau Supabase Auth.
  3. Butuh B2B Fast-Track: Jika lu lagi pitching ke client enterprise yang butuh SSO/SAML & Team Organization minggu depan, Clerk adalah jalan pintas terbaik yang sepadan dengan biayanya.

Pilih tool yang menyelesaikan masalah lu hari ini, tapi pastikan arsitektur kode lu cukup rapi (misal: bungkus fungsi auth di balik abstraksi interface) supaya lu gak nangis kalau suatu hari harus migrasi provider auth!

Butuh penyesuaian khusus untuk project Anda?

Jika situasi operasional atau arsitektur sistem bisnis Anda membutuhkan solusi kustom, diskusikan langsung bersama tim engineer kami. Anda juga bisa melihat rincian layanan vour.dev atau menghitung estimasi biaya project lebih dulu.

Mulai Project