Auth systems and your migration
What your auth system means for a move to CapyDB - Clerk, BetterAuth, Auth.js, Lucia, and Supabase Auth each change the plan differently.
CapyDB is plain Postgres: there is no auth schema, no auth.uid(), no PostgREST enforcing RLS
per request. Whether that matters - and how much work it creates - depends entirely on where your
identity system lives. capydb migrate scan detects which of these you are.
Clerk (or any external IdP): the best case
Your identity lives outside the database, so the database move cannot break login. Two things to check:
- User rows. The common pattern keeps a
userstable in your own schema synced from Clerk webhooks - that table rides the dump untouched. - RLS policies keyed on the provider JWT (
auth.jwt()->>'sub'via PostgREST). These are dropped during import and are inert on plain Postgres anyway. Move that authorization into your server-side data layer: enumerate every policy (select * from pg_policies- the import preflight lists the affected tables for you), and give each one a named guard in the module that owns that table's queries. App-layer guards are easier to test than RLS and work through connection poolers.
If several services share one database credential, RLS was also defense-in-depth across all of
them. In that case keep a simple tenant-scoping policy keyed on a per-transaction session
setting (SET LOCAL app.org_id = ...) in addition to the app guards - and note it must be set
per-transaction to survive transaction pooling.
BetterAuth, Auth.js (NextAuth), Lucia: nothing to do
These store users, sessions, and accounts in your application schema - the dump brings your entire auth state along. Checks:
- Confirm their tables live in a schema the import carries (
publicor one the preflight lists as an app schema). - JWT-session mode (Auth.js) has no database coupling at all.
- BetterAuth secondary storage (Redis, if configured) is outside the database and unaffected.
- Cookie domains and
*_URLenv vars don't change - onlyDATABASE_URLdoes.
Supabase Auth: migrate auth first
If your app calls supabase.auth.* for sign-in and your tables have foreign keys into
auth.users, Supabase Auth is your identity system. A database-only migration strands it: the
auth schema does not come along, those FKs have no target, and every login path breaks.
The order that works:
- Migrate identity to an external provider (Clerk is the well-trodden path) or a DB-native
library (BetterAuth), including re-pointing
auth.usersFKs at your own users table. - Re-run
capydb migrate scan- your app is now one of the easy cases above. - Then do the database move.
The import preflight sizes this for you before you commit to anything:
it reports every FK into provider-managed schemas and every table with auth.*()-bound RLS.