Guides

Migrate a Lovable Cloud project to your own Supabase

Atomart· February 11, 2026· updated July 13, 2026· 6 min read

Migrate a Lovable Cloud project to your own Supabase

Lovable Cloud gives you a Supabase backend without the Supabase dashboard. That is fine until you need direct database access, your own billing, custom Edge Functions, or a project you fully control. At that point you move the schema, the data, the auth users, and the storage objects into a Supabase project you own.

This guide covers what actually moves, in what order, and the failures you will hit.

What Lovable Cloud gives you

Under the hood, Lovable Cloud is a real Postgres database on Supabase infrastructure. You get:

  • A public schema with your tables, RLS policies, and functions
  • An auth schema with your users, bcrypt password hashes included
  • Storage buckets and objects
  • Edge Functions and secrets — these do not migrate as data, you redeploy them

What you usually do not have is a connection string or a service role key printed in a dashboard. You read them from the project settings Lovable exposes, or from the Supabase project that backs it.

Migration order (this order matters)

Postgres rejects inserts that reference rows that do not exist yet, and it rejects DDL that references types or extensions that are not installed. Run the steps in dependency order:

  1. Extensions (uuid-ossp, pgcrypto, postgis, ...)
  2. Types and enums
  3. Tables without foreign keys
  4. Foreign key constraints
  5. Indexes
  6. Functions
  7. Triggers
  8. RLS policies
  9. Publications (for Realtime)

Then load data, then auth, then storage.

Flatten this order and you get relation does not exist on the DDL step and foreign key violation on the data step.

Step 1 — Recreate the schema

There is no pg_dump inside a browser or an Edge Function, so the schema is rebuilt by querying information_schema and pg_catalog and generating DDL from the result. See schema replay for the catalogs involved, or the migrate schema doc for the step-by-step.

Check the destination is empty before you start:

select table_name
from information_schema.tables
where table_schema = 'public'
order by table_name;

If that returns rows on a project you thought was blank, stop. Reapplying DDL over existing objects raises relation already exists.

Step 2 — Move the data

Load tables in foreign-key order, parents before children, batched. A batch size of 1000 rows is a reasonable default; larger batches raise memory pressure on the pooler.

After every table with a serial or identity column, reset the sequence or the next insert collides on the primary key:

select setval(
  pg_get_serial_sequence('public.orders', 'id'),
  (select coalesce(max(id), 1) from public.orders)
);

Skip this and you get a duplicate key error the moment your app inserts its next row. See sequence resync.

Step 3 — Move the auth users

This is the part people get wrong. The Supabase auth.admin.createUser() API does not accept a precomputed bcrypt hash, so if you recreate users through it, everyone has to reset their password.

Instead, insert directly into auth.users, preserving both the id (foreign keys in public point at it) and the encrypted_password column. The migrate auth doc walks the full step.

Step 4 — Move storage

Storage objects are files in buckets, not database rows. You recreate each bucket, then copy each object. Recreating a bucket that already exists raises duplicate key value violates unique constraint "buckets_pkey", so create buckets with an existence check first.

Connecting

Both source and destination need a Postgres connection string. If your network is IPv4-only, the direct db.<ref>.supabase.co host fails with ENETUNREACH — use the connection pooler host instead. Supabase documents both hosts under connecting to Postgres, and the connection string builder assembles the right URL.

SupaMigrate runs all of the above from the browser, so your service role key never touches a server. If you would rather do it by hand, the steps above are the whole job.

FAQ

Does migrating break my users' passwords?

No, if you copy the encrypted_password bcrypt hash directly into auth.users on the destination. The Supabase admin API cannot set a hash, which is why the migration uses a direct SQL insert. Users keep their existing passwords and do not re-login.

Do Edge Functions and secrets move automatically?

No. Edge Functions are code, not database rows, and secrets are stored outside Postgres. You redeploy the functions to the destination project and re-add the secrets by hand. The migration handles schema, data, auth, and storage.

Can I keep using the source project during migration?

Yes. The source is read-only throughout — the migration only issues SELECT and catalog queries against it. Nothing is written to or deleted from Lovable Cloud, so you can run the migration while the app is live and cut over afterwards.

Atomart

Founder, SupaMigrate

Builder of SupaMigrate. Works on Postgres, Supabase, and the unglamorous parts of database migration — schema replay, auth hash preservation, and connection pooling.

Related reading