12 Nov 2026 · 6 min read

Expo auth: Clerk vs Supabase vs Better Auth

Clerk, Supabase or Better Auth in Expo: which ships prebuilt native screens, Expo Go support, session storage, pricing and account deletion.

Of the three, only Clerk ships prebuilt sign-in screens for native Expo apps. Its AuthView component draws the sign-in and sign-up flow in SwiftUI on iOS and Jetpack Compose on Android. It is in beta and needs a development build, so it does not run in Expo Go. Supabase Auth and Better Auth ship no native screens. You call their SDK and build the forms yourself. Supabase's pre-built UI components are for the web.

Clerk also has a hosted sign-in page that opens in an in-app browser session, which works in Expo Go, and its web components cover Expo web. Expo's authentication guide lists all three as ready-made options. ReadyNative supports all three, so the rest of this post compares them on sign-in methods, Expo Go, where the session lives, the backend, account deletion and cost.

Which auth option to pick firstThree branches. Prebuilt native sign-in screens lead to Clerk. A Postgres database with row-level security leads to Supabase. Owning the user table on your own API routes leads to Better Auth.Want prebuilt native screens?user management, no database to runClerkNeed a Postgres database?row-level security on the same accountSupabaseWant to own the user table?your API routes and your databaseBetter Auth
Start from the need that matters most. All three work with the same @/lib/auth API.

The comparison in one table

ClerkSupabase AuthBetter Auth
Prebuilt native UIYes, in beta: AuthView and UserProfileView on iOS and AndroidNo: SDK calls only; its pre-built UI is for the webNo: SDK calls only
Email sign-inEmail and password, with a 6-digit codeEmail and password, with email confirmation onEmail and password, with a reset link
Apple and Google (ReadyNative module)Apple native; Google in the browserApple native (ID token); Google in the browserApple and Google in the browser; native Apple not wired
Runs in Expo GoHosted and custom flows yes; AuthView needs a dev buildYes; a dev build once you add a native libraryYes, per the module docs
Session stored inexpo-secure-store, through Clerk's token cacheThe storage adapter: kv-store, MMKV or AsyncStorageexpo-secure-store (session cookie)
BackendClerk's hosted user databasePostgres with row-level securityYour API routes and your database
Account deletionuser.delete() from Settings; switch it on in the dashboarddelete_user() SQL migration, plus Storage cleanupauthClient.deleteUser(), enabled on the server

Prebuilt UI: what is native and what you build

Clerk's native components are the only prebuilt native screens in this comparison. AuthView covers sign-in and sign-up, and it shows a button for each social connection you enable in the Clerk dashboard. UserProfileView manages the account, and UserButton opens it from an avatar. The components need the @clerk/expo-native-components package, a development build and Expo SDK 54 or later.

The social buttons appear before their credentials are set up. Google needs iOS, Android and Web client IDs registered with Clerk, and Apple needs your bundle id added as a native application. Without them, a tap fails with an error. ReadyNative's Clerk module skips AuthView and ships its own screens on Clerk's hooks, so the same code runs in Expo Go.

Supabase and Better Auth have nothing to drop in. Their SDKs give you the call, and the form is yours:

// Supabase
await supabase.auth.signInWithPassword({ email, password });

// Better Auth
await authClient.signIn.email({ email, password });

Clerk's custom flow works the same way, through the useSignUp() hook, if you skip the native components.

Sign-in methods

All three offer email and password, but each one handles the second step differently. Clerk asks for a 6-digit code at sign-up and again on password reset, and it mails the code. Supabase keeps email confirmation on by default, so the new user signs in after clicking the link. Better Auth's reset link needs an email provider, which you plug into src/server/email.ts. Until you do, the dev server logs a notice without the link.

Apple and Google split the same way. On iOS, Clerk and Supabase both take a native Apple credential: Clerk through its Apple token strategy, Supabase with signInWithIdToken. ReadyNative's Better Auth module runs Apple through the browser, because native Apple is not wired there. Better Auth's Expo guide does document an ID-token option you could add. Google opens the system browser in all three modules.

Expo Go or a development build

ReadyNative marks all three auth modules as working in Expo Go. The exceptions come from what you add yourself. Clerk's native components need a development build. Supabase's Expo guide runs in Expo Go until you pass options to a plugin or add a native library that Expo Go lacks. For the rules, read Expo Go vs development build.

Where the session lives

Clerk keeps its client token in expo-secure-store through Clerk's token cache. Better Auth keeps its session cookie in SecureStore and caches the session data there too. Both follow the storage guide's rule that tokens belong in expo-secure-store.

Supabase is the exception. ReadyNative persists its session through the storage adapter, so the session sits in expo-sqlite/kv-store, MMKV or AsyncStorage, whichever you chose. Supabase's Expo guide shows an optional pattern that encrypts the session and keeps only the key in SecureStore. The ReadyNative module does not use it. If that matters for your app, read the key/value storage comparison before you ship.

The backend you get

Clerk hosts the users, so you run no user database. Your API routes check the caller with @clerk/backend and your secret key or JWT key. Supabase gives you a Postgres database in the same project, and row-level security decides which rows each signed-in user can read. Better Auth stores users in your own database, reached from your own API routes. ReadyNative's Better Auth module starts on an in-memory adapter that forgets every user on restart. Swap in Postgres, Drizzle, Prisma or Kysely before you ship.

Account deletion

App Review Guideline 5.1.1 asks an app that lets people create an account to offer account deletion inside the app. Each ReadyNative module adds a Delete account row to Settings, and the setup differs. With Clerk, the row calls user.delete(), and you must switch on Allow users to delete their accounts in the Clerk dashboard, or the call throws. With Supabase, the anon key cannot delete auth users, so the module ships a SQL migration with a delete_user() function (the Supabase walkthrough has the SQL), plus a second migration that removes the user's Storage files first. With Better Auth, the row calls authClient.deleteUser(), which the server config enables. If the session is older than the freshness window, one day by default, the app asks for the password again.

What each one costs

These are the figures on each pricing page as of 12 Nov 2026. Free tiers change, so check the page before you choose.

Pick the one that fits

None of the three is the best choice for every app. Pick the trade-off you can live with. The screens and the @/lib/auth API stay the same if you change your mind.

Read next: the full Supabase walkthrough, with redirect URLs, password reset and account deletion, is in Supabase auth in Expo: email, Apple and Google. Each option has a page at /stack/auth/clerk/, /stack/auth/supabase/ and /stack/auth/better-auth/, and the module docs are in the auth docs.

FAQ

Which auth providers have prebuilt UI components for Expo?

Clerk is the only one of the three with prebuilt native screens: AuthView and UserProfileView render in SwiftUI on iOS and Jetpack Compose on Android. That part is in beta and needs a development build. Supabase Auth and Better Auth give you SDK calls, so you build the forms yourself.

Does Clerk's AuthView work in Expo Go?

No. The native components need a development build, made with npx expo run:ios, npx expo run:android or EAS Build. Clerk's hosted sign-in page and its custom hook flow both work in Expo Go.

Where does Supabase keep the session in a ReadyNative app?

In the storage adapter you chose: expo-sqlite/kv-store, MMKV or AsyncStorage, not SecureStore. Clerk keeps its token in expo-secure-store, and Better Auth keeps its session cookie there.

What do Clerk, Supabase and Better Auth cost?

Clerk's Hobby plan is free up to 50,000 monthly retained users per app, and Supabase's Free plan includes 50,000 monthly active users. Better Auth is MIT licensed, so you pay only for the server and database you run. Figures are from the pricing pages on 12 Nov 2026.

More guides