Migrate from Neon
Move a Neon Postgres database to SupaHost: dump it over Neon's direct (non-pooled) endpoint, load it into a project, replace the Neon serverless driver and verify.
Neon is standard Postgres, so a Neon database moves to SupaHost as a pg_dump file. The one change people miss is in the app: Neon's serverless driver talks to Neon's own proxy, while a SupaHost project is reached through the Data API (supabase-js or HTTP). Plan for that code change as well as the data copy.
Plan
- Size. Check the database size in the Neon console. It must fit your plan's shared database quota (8 GB Builder, 25 GB Pro, 50 GB Business).
- Branch. Dump from the Neon branch that holds production data, usually
main. - Load path. On Business and Enterprise you restore over the SSH tunnel. On Builder and Pro you load through Studio, MCP or a script, or stage the dump in a Supabase Cloud project and use the one-click import.
- Code. List every place that uses
@neondatabase/serverless,pgor an ORM againstDATABASE_URL.
Export from Neon
In the Neon console's Connect dialog, turn connection pooling off. The direct host has no -pooler in its name, which is what pg_dump needs.
pg_dump -Fc --no-owner --no-privileges -n public \
"postgresql://bookings_owner:<password>@ep-quiet-dawn-123456.eu-central-1.aws.neon.tech/bookings?sslmode=require" \
-f bookings.dump
Use version 17 client tools. A compute that has scaled to zero wakes up for the dump. -n public leaves out Neon's own schemas (such as neon_auth if you used Neon Auth); users move to Supabase Auth instead (see Moving Auth users between projects for the admin API approach).
Prepare the target
Create the extensions the dump relies on, in Studio's SQL editor:
create extension if not exists pg_trgm with schema extensions;
create extension if not exists vector with schema extensions;
Load
Business and Enterprise:
ssh -N -L 6543:127.0.0.1:5432 [email protected] &
pg_restore --no-owner --no-privileges -d "postgresql://postgres:<password>@127.0.0.1:6543/p_app_one" bookings.dump
Get the password from Dashboard → your project → Connect → Database → Show connection string. Read through any errors pg_restore prints; most come from objects that already exist.
Builder and Pro: restore the dump into a temporary Supabase Cloud project and run the one-click import, or apply the schema in Studio's SQL editor (pg_restore --schema-only -f schema.sql bookings.dump gives you the SQL) and load tables from CSV or with a supabase-js script using the service_role key.
Secure and tune
Enable RLS on every table in public, because the Data API exposes that schema. The policy below assumes guest_id holds Supabase Auth user IDs once your users have moved:
alter table public.bookings enable row level security;
create policy "guests see their bookings" on public.bookings
for select to authenticated using ((select auth.uid()) = guest_id);
analyze;
Switch the app
Replace the Neon driver with supabase-js:
// before
const rows = await sql`select * from bookings where guest_id = ${userId}`
// after
const { data: rows, error } = await supabase
.from('bookings')
.select('*')
.eq('guest_id', userId)
Queries that don't map cleanly to the query builder can become database functions called with supabase.rpc().
Verify
Run select count(*) on your main tables in both databases, exercise the key screens, and keep the Neon project until the new setup has run for a few days.