# Migrate from Amazon RDS

> Move an Amazon RDS or Aurora PostgreSQL database to SupaHost: reach it from a machine in the VPC, dump with pg_dump, skip AWS-only extensions, restore and switch your app to the Data API.

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

Amazon RDS for PostgreSQL (and Aurora PostgreSQL) moves to SupaHost with `pg_dump` and a restore. The two RDS-specific steps are reaching the database, which usually sits inside a VPC, and leaving out AWS-only extensions and roles. After that it's the same as any Postgres move.

## Plan

- **Size.** The database must fit your plan's shared quota (8 GB Builder, 25 GB Pro, 50 GB Business). For large databases, Business is the practical choice because you can restore directly over the SSH tunnel.
- **Network.** Run the dump from a machine that can reach the RDS endpoint: an EC2 instance in the same VPC, a bastion host, or your laptop if the instance is publicly accessible and its security group allows your IP on port 5432.
- **App access.** EC2, ECS or Lambda code that connects with a Postgres driver will need to use the Data API instead, since a SupaHost project's Postgres isn't reachable over the internet. Lambda in particular fits the HTTP model well.

## Export from RDS

```bash
pg_dump -Fc --no-owner --no-privileges -n public \
  -h fleet-db.c9abcdxyz.eu-west-2.rds.amazonaws.com -U fleet_admin -d fleet \
  -f fleet.dump
```

Use pg_dump 17. `--no-owner --no-privileges` strips grants to `rds_superuser` and other RDS roles. `-n public` keeps only your application schema; if you use more schemas, add one `-n` per schema.

## Transform

Check which extensions the source uses:

```sql
select extname, extversion from pg_extension order by 1;
```

Skip AWS-only ones such as `aws_s3`, `aws_commons` and `aws_lambda`; any functions that call them need rewriting (for example, an S3 export can become an Edge Function). Create the rest in the target project, in the `extensions` schema:

```sql
create extension if not exists postgis with schema extensions;
create extension if not exists pgcrypto with schema extensions;
```

## Load

**Business and Enterprise:**

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

`-j 4` restores tables in parallel. The password comes from Dashboard → your project → **Connect** → **Database** → **Show connection string**.

**Builder and Pro:** restore into a temporary Supabase Cloud project and use the [one-click import](/kb/migrate-from-supabase-cloud), or, for small databases, run the schema in Studio's SQL editor and load tables from CSV or through a supabase-js script with the `service_role` key.

## After loading

```sql
-- every public table is reachable through the Data API: lock it down
alter table public.vehicles enable row level security;
alter table public.trips enable row level security;
analyze;
```

Add policies, then recreate any scheduled work you ran with EventBridge or Lambda as pg_cron jobs:

```sql
select cron.schedule('close-trips', '0 * * * *', $$
  update public.trips set status = 'closed'
  where status = 'open' and ended_at < now() - interval '1 hour'
$$);
```

## Switch the app and verify

Replace the RDS host and credentials with `SUPABASE_URL` and the `service_role` key (server code) or anon key (client code), and move queries to supabase-js or `rpc()`. Compare `select count(*)` per table between RDS and SupaHost, test the main flows, and take a final RDS snapshot before you delete the instance.

## Related

- [Importing data (CSV, SQL dumps)](/docs/database/import-data)
- [Postgres extensions](/docs/database/extensions)
- [SSH access and direct Postgres](/docs/platform/ssh)
- [Scheduled jobs with pg_cron](/docs/cron-queues/cron)
