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.
The comparison in one table
| Clerk | Supabase Auth | Better Auth | |
|---|---|---|---|
| Prebuilt native UI | Yes, in beta: AuthView and UserProfileView on iOS and Android | No: SDK calls only; its pre-built UI is for the web | No: SDK calls only |
| Email sign-in | Email and password, with a 6-digit code | Email and password, with email confirmation on | Email and password, with a reset link |
| Apple and Google (ReadyNative module) | Apple native; Google in the browser | Apple native (ID token); Google in the browser | Apple and Google in the browser; native Apple not wired |
| Runs in Expo Go | Hosted and custom flows yes; AuthView needs a dev build | Yes; a dev build once you add a native library | Yes, per the module docs |
| Session stored in | expo-secure-store, through Clerk's token cache | The storage adapter: kv-store, MMKV or AsyncStorage | expo-secure-store (session cookie) |
| Backend | Clerk's hosted user database | Postgres with row-level security | Your API routes and your database |
| Account deletion | user.delete() from Settings; switch it on in the dashboard | delete_user() SQL migration, plus Storage cleanup | authClient.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
- Clerk: the Hobby plan is free up to 50,000 monthly retained users per app, and Pro starts at $25 a month. Source: clerk.com/pricing.
- Supabase: the Free plan includes 50,000 monthly active users, and Pro starts at $25 a month with 100,000 included. Source: supabase.com/pricing.
- Better Auth: the library is MIT licensed, so it is free to use. You pay for the server and database you run. Source: the license on GitHub.
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
- Clerk when you want prebuilt native screens and user management, including organizations, and would rather pay for them than run a user database.
- Supabase when you also need Postgres with row-level security behind the same account. Plan for the session living in your storage adapter, or add the encryption pattern yourself.
- Better Auth when the user table has to be yours, on your own API routes and database, and you accept the work of running them.
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
- Unistyles 3 with Expo: a working setup
- Expo environment variables: which are public?
- TanStack Query in Expo: offline and refetch
- Expo zustand: persist a store across restarts
- jest-expo setup, Expo Router tests and fixes
- AsyncStorage vs MMKV vs expo-sqlite/kv-store
- Expo i18n: i18next or Lingui, compared
- Expo android widgets: expo-widgets on SDK 58
- Tamagui in Expo: setup, styling and themes
- Best paywall tools for Expo in 2026
- Expo widgets on iOS: a working setup
- RevenueCat subscriptions in an Expo Router app
- Supabase auth in Expo: email, Apple and Google
- Expo push notifications: setup, token, testing
- Expo Go vs development build: limitations
- The best Expo boilerplates, compared