It's one of the most common questions in the self-hosting community: "Can I just point Supabase at my managed Postgres instead of running the bundled database container?" The appeal is obvious. Managed Postgres services like AWS RDS, Aurora, Google Cloud SQL, or DigitalOcean Managed Databases give you automated backups, point-in-time recovery, failover, and patching without you operating Postgres yourself. If you're already weighing the true cost of self-hosting, offloading the hardest part — the database — sounds like a win.
The short answer: it's technically possible, but it's far harder than the documentation implies, and for most teams it isn't worth it. This guide walks through exactly what breaks, why, and the setups that actually work.
Why the bundled Postgres image is not just "Postgres"
When you run the official self-hosted stack from the installation docs, the db service isn't vanilla Postgres. Supabase ships a custom supabase/postgres image that bakes in a long list of extensions and runs an elaborate set of bootstrap scripts on first start. Auth, Storage, Realtime, PostgREST, the Studio dashboard, and the connection pooler all assume that work has already been done.
Two categories of things live inside that image that a managed database won't have:
Custom roles. The stack expects specific Postgres roles to exist with specific privileges: supabase_admin (effectively a superuser), authenticator, supabase_auth_admin, supabase_storage_admin, supabase_realtime_admin, plus the anon, authenticated, and service_role roles that Row Level Security depends on. Each service connects as a different role and expects precise grants.
Custom extensions. This is where managed databases fall down hardest. Supabase relies on extensions you generally cannot install on a restricted managed service:
pg_net— async HTTP from Postgres, used by database webhookspgsodiumandsupabase_vault— encryption and secrets storagepg_graphql— the GraphQL APIpgjwt— JWT helpers used by older auth flowspgmq,wrappers,pg_cron— queues, foreign data wrappers, scheduled jobs
On AWS RDS or Aurora you don't get true superuser — you get rds_superuser, which can't CREATE EXTENSION for anything outside the provider's approved allowlist. Most of the extensions above simply aren't on that list. This isn't a configuration you can flip; it's a hard boundary of the managed service. (See our guide to managing Postgres extensions for the full picture of what the stack actually loads.)
What it takes to swap the database
If you still want to try, here's the shape of the work. You edit docker-compose.yml to remove the db service entirely, then redirect every other service to your external host. In your environment file, that means setting:
POSTGRES_HOST=your-db.cluster-xxxx.us-east-1.rds.amazonaws.com POSTGRES_PORT=5432 POSTGRES_DB=postgres POSTGRES_PASSWORD=your-strong-password
Then you have to manually reproduce everything the bundled image does on first boot:
- Create the roles (
supabase_admin,authenticator,supabase_auth_admin,supabase_storage_admin,supabase_realtime_admin, and the API roles) with the correct grants andLOGINattributes. - Create the
_supabasedatabase. This is a separate, hard-coded database the stack uses internally for the analytics service (Logflare) and the Supavisor connection pooler's metadata. Miss it and those containers crash-loop. - Create the schemas —
auth,storage,realtime,_realtime,graphql,graphql_public,extensions,vault, and others — with ownership assigned to the right admin roles. - Install the extensions your features need. This is the step that usually ends the experiment on a managed service.
- Run the service migrations for Auth (GoTrue), Storage, and Realtime, in the right order, since they no longer self-bootstrap against a database that already has their schemas.
One operator on the Supabase GitHub discussions described getting RDS working as "a real pain to setup [that] took 2 weeks of custom CloudFormation and shell scripting to alter the supabase/postgres migration files and align extensions, role grants and migration order." That's the honest cost. And every time Supabase ships a new image — like the June 2026 move to Postgres 17 — you re-validate all of it by hand.
The setup that actually works: a fully-controlled Postgres
There's an important distinction the community keeps coming back to. "External database" and "managed database" are not the same thing.
If you run your own Postgres — on a dedicated VM, a separate Docker host, or a bare-metal box where you have genuine superuser and can install any extension — then pointing the Supabase services at it is reasonable. You can install the full supabase/postgres package contents, create every role, and keep the database on its own machine for isolation or scaling. This is a legitimate architecture and is roughly how production deployments separate the data tier.
What does not work cleanly is a restricted managed service. RDS, Aurora, and Cloud SQL deliberately lock down superuser and extension installation precisely because that's how they guarantee their backup and HA promises. Those same restrictions are what break Supabase. You can't have both the managed-service guarantees and the unrestricted Postgres the stack assumes.
So the practical decision tree is:
- Want managed-service convenience (RDS/Aurora) AND full Supabase features? Not realistically possible. Pick one.
- Want a separate database tier you fully control? Use a self-managed Postgres VM with the Supabase image's roles and extensions. Workable, but you're back to operating Postgres yourself — backups, patching, failover and all.
- Want the least operational pain? Run the bundled
supabase/postgresimage as designed and solve durability with proper backups and replication around it.
Solving the real problem: durability without the glue code
Strip away the implementation details and the actual motivation is almost always one thing — people want the reliability of a managed database (automated backups, easy restore, no 3 a.m. recovery scrambles) without giving up self-hosting. You don't need to swap out Postgres to get that. You need a backup and recovery story that's as boring and dependable as RDS's.
That's exactly the gap Supascale is built to close. Instead of fighting role grants and extension allowlists, you run the standard, fully-featured Supabase image — every extension intact — and get the durability layer on top:
- Automated, scheduled backups to S3-compatible storage with one-click restore, so you get the "managed database" safety net without a managed database. (See creating backups.)
- The complete extension set working out of the box —
pg_net,pgsodium, Vault,pg_graphql, and the rest — because you're running the real image, not a stripped-down managed instance. - No vendor lock-in and no glue code to re-validate every time Supabase ships a new Postgres image.
You keep full control of your data and your server, and the part you actually wanted from RDS — "I never have to think about backups" — is handled. For teams comparing total cost, that's a one-time $39.99 against weeks of CloudFormation and an ongoing managed-database bill.
The honest bottom line
Can you run self-hosted Supabase against an external Postgres? Yes — if it's a database you fully control. Can you run it against AWS RDS, Aurora, or another locked-down managed service while keeping Supabase's features? Not without significant, fragile custom work that breaks on every upgrade, and even then you'll lose features that depend on unavailable extensions.
For nearly everyone, the better path is to run the bundled image as designed and put a solid backup and restore process around it. That gives you the durability you were chasing without inheriting a maintenance burden that grows with every release.
