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.

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.
1. Developer Experience (DX) & Kecepatan Integrasi

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.
// 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.
// 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).
// 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

Pertanyaan paling krusial pas milih Auth provider: "Di mana data user gue disimpan, dan seberapa gampang gue join data user dengan data bisnis?"
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
JOINlangsung antara tabelUserdengan tabelOrder,Post, atauSubscriptiontanpa latency jaringan tambahan. - Minus: Database lu ikut menampung beban I/O session. Kalau pakai strategy session
databasealih-alihjwt, 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:
- 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.
- Sinkronisasi via Webhook: Bikin webhook endpoint untuk mendengarkan event
user.createddanuser.updateddari 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.
-- 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.
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.
-- 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:
// 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.
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:
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:
- Evaluasi DB Utama: Kalau DB lu udah Postgres di Supabase, jangan muter-muter—langsung pakai Supabase Auth.
- 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.
- 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