Miss Supatool

Migrate a Supabase project to another one

Published · by

Lire en français

In short. To migrate a Supabase project, first recreate the schema in the target, then copy the tables in foreign-key order and the files bucket by bucket, and finally reset the sequences. User accounts, Edge Functions, secrets and sign-in settings have to be moved separately, and storage files are never part of a database dump.

Moving to another organization, starting over from a clean project after a prototype, duplicating a database for testing: one day, you need to copy a Supabase project to another. Here is what to move, in which order, and the pitfalls that make a migration fail.

What needs to move

A Supabase project is made of several layers, which are not copied the same way:

Two methods

From the command line. You export the database (with pg_dump or the supabase db dump command of the CLI), then restore it into the new project with psql. It is the most complete route for the database, but it requires installing tools and having the connection string of both databases. Storage files still have to be copied separately.

Through the APIs, from the browser. Each project exposes a REST API (PostgREST) that publishes the description of its tables and keys, and a storage API that lists, downloads and uploads files. That is enough to copy data and files without installing anything. Creating the schema also requires the Supabase Management API.

The steps of a migration without bad surprises

  1. Prepare the target. Create the project, or pick an empty one.
  2. Recreate the schema before the data. A row cannot be inserted into a table that does not exist.
  3. Copy the tables in foreign-key order. If members.club_id points to clubs.id, copy clubs first, otherwise every member will be rejected.
  4. Copy the files, bucket by bucket.
  5. Reset the sequences. This is the most common oversight. You copy 1,250 orders with their ids from 1 to 1,250, but the target's sequence is still at 1. The first order your app creates will ask for id 1 and be rejected. A setval fixes it: select setval(pg_get_serial_sequence('public.orders', 'id'), (select max(id) from public.orders));
  6. Check: count the rows on both sides, then switch the URL and keys in your app and test it.

Two more traps during the copy: the target's triggers run and may rewrite what you insert (an updated_at column, an audit log), and a GENERATED ALWAYS column rejects any value. Those columns must then be left out of the copy.

How Miss Supatool helps

Miss Supatool is a web app that runs this migration in five steps: Projects, Content, Schema, Copy, Report. Its interface is in French only.

Keys are never saved: they stay in memory for the life of the tab. Project creation, schema copy and sequences go through a relay, with your Supabase personal access token.

Supabase is deprecating the anon and service_role keys by the end of 2026, in favor of sb_publishable_… and sb_secret_… keys. Miss Supatool recognizes an sb_secret_… key but flags it: on a new project, it was not accepted everywhere the same project's service_role key was. If calls fail, use the service_role key while it still exists.

What the tool does not copy

Files travel through your browser: a very large object may fail. Project creation and schema copy only work with projects hosted by Supabase.

Miss Supatool is an independent app, neither affiliated with nor endorsed by Supabase. Supabase is a trademark of its owner. The French original of this guide is Migrer un projet Supabase vers un autre.

Frequently asked questions

Can you migrate a Supabase project without the command line?

Yes, for the schema, the data and the files: the Supabase APIs are enough. That is the approach Miss Supatool takes. User accounts and project settings still have to be moved separately.

Are RLS policies copied?

Yes, along with the schema, for the chosen schema. Storage policies, which live in another schema, have to be replayed separately.

Why is the service_role key required?

It bypasses RLS: that is what allows reading every row of the source and writing to the target. It therefore opens the whole database. Use it from a trusted device and regenerate it at the slightest doubt. Supabase is deprecating it by the end of 2026, in favor of sb_secret_… keys.

Can the migration damage the source project?

Miss Supatool never writes to it: its client refuses any write request to the source before sending it. And by default, every step starts with a dry run that reads everything and writes nothing.

References