Migrate from Supabase Auth
1. Export from Supabase
Section titled “1. Export from Supabase”Self-hosted (or via a support-requested dump on the hosted platform), it’s your database:
SELECT id, email, raw_user_meta_data->>'full_name' AS display_name, encrypted_passwordFROM auth.usersWHERE deleted_at IS NULL;encrypted_password is a standard bcrypt hash ($2a$…). On hosted Supabase the column is not
exposed through the API — ask Supabase support for an auth.users dump, or skip hashes entirely
(Axowl doesn’t need them; see below).
2. Import
Section titled “2. Import”const rows = supabaseUsers.map(u => ({ email: u.email, displayName: u.display_name || null, sourceUserId: u.id, // Supabase auth.users.id (UUID) passwordHashAlgorithm: u.encrypted_password ? "bcrypt" : null, passwordHash: u.encrypted_password || null,}));// POST in batches of 500 with source: "supabase" — loop as in the Clerk guide.See the Clerk guide for the batching loop and foreign-key re-mapping SQL.
Because Supabase’s auth.users.id is usually the FK all over your schema, keep the
sourceUserId → endUserId map from the import response — that map is your migration.
Gotchas
Section titled “Gotchas”- RLS policies referencing
auth.uid()are the real migration work — they die with Supabase Auth. Plan how Axowl’s JWT (issued per App Group) replaces those checks in your API layer. - Social login carries over by email; magic-link users carry over with zero friction (Axowl’s default login is magic link).
- Hashes are stored dormant — see how the import works.