# Migrate from Vercel Postgres

> Move a Vercel Postgres (Neon-backed) database to SupaHost: dump it with the non-pooling URL, load it into a project and replace @vercel/postgres with supabase-js in your Vercel app.

Source: https://supahost.app/kb/migrate-from-vercel-postgres · Updated 2026-11-11

Vercel Postgres databases run on Neon, and Vercel has moved existing stores over to Neon's integration. So the data side is a Neon-style `pg_dump`, and the app side is replacing `@vercel/postgres` with supabase-js. Your Next.js app can stay on Vercel; only the database moves.

## Plan

- **Size.** Check the database size in the Vercel or Neon dashboard. It must fit your SupaHost plan's shared database quota (8 GB Builder, 25 GB Pro, 50 GB Business).
- **Load path.** Business and Enterprise restore directly over the SSH tunnel. On Builder and Pro, stage the dump in a Supabase Cloud project and use the one-click import, or load smaller databases through Studio.
- **Code.** Find every `sql` tagged-template call from `@vercel/postgres` and every ORM using `POSTGRES_URL`. Vercel Functions can't open a Postgres connection to a SupaHost project, so these become supabase-js calls.

## Export

Pull the env vars locally and dump with the non-pooled URL:

```bash
vercel env pull .env.migration
source .env.migration
pg_dump -Fc --no-owner --no-privileges -n public "$POSTGRES_URL_NON_POOLING" -f shop.dump
```

Use pg_dump 17. The pooled `POSTGRES_URL` goes through a transaction pooler and isn't suitable for dumps.

## Load

**Business and Enterprise:**

```bash
ssh -N -L 6543:127.0.0.1:5432 supahost@acme.supahost.space &
pg_restore --no-owner --no-privileges \
  -d "postgresql://postgres:<password>@127.0.0.1:6543/p_app_one" shop.dump
```

Copy the password from Dashboard → your project → **Connect** → **Database** → **Show connection string**.

**Builder and Pro:** restore `shop.dump` into a temporary Supabase Cloud project, then run the [one-click import](/kb/migrate-from-supabase-cloud). For a few small tables, `pg_restore --schema-only -f schema.sql shop.dump` gives SQL to run in Studio's SQL editor, and the table editor can import each table from CSV.

## Secure the tables

```sql
alter table public.orders enable row level security;
create policy "customers read own orders" on public.orders
  for select to authenticated using ((select auth.uid()) = customer_id);
analyze;
```

## Switch the app

In Vercel → your project → Settings → Environment Variables, add:

```bash
NEXT_PUBLIC_SUPABASE_URL=https://app-one.acme.supahost.space
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOi...
SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOi...   # no NEXT_PUBLIC_ prefix: server only
```

Then replace queries:

```ts
// before (@vercel/postgres)
const { rows } = await sql`select id, total from orders where customer_id = ${userId}`

// after (supabase-js, in a Server Component or Route Handler)
const { data: rows, error } = await supabase
  .from('orders')
  .select('id, total')
  .eq('customer_id', userId)
```

Use `@supabase/ssr`'s `createServerClient` on the server so RLS sees the signed-in user. If you add Supabase Auth, add `https://*.vercel.app/**` to the project's redirect URLs (Dashboard → your project → **Auth** tab) so preview deployments can sign in.

## Verify

Compare `select count(*)` on each table, deploy a preview, and click through checkout or whatever your main flow is. Remove the Vercel Postgres store only after production has run on SupaHost for a while.

## Related

- [Can I use SupaHost with a Next.js app on Vercel?](/kb/nextjs-vercel)
- [Deploying your app on Vercel](/docs/integrations/vercel)
- [Auth in Next.js (App Router)](/docs/auth/nextjs)
- [Migrate from Neon](/kb/migrate-from-neon)
