← All playbooks
Backend migration

PostgreSQL → Supabase

Move PostgreSQL schemas, data, extensions, roles, sequences, replication, and application access into Supabase Postgres without treating a dump file as a finished backend.

Typical timeline10–25 business days40–90 hours active work
Statusneeds review
Source profilePostgreSQL documentation reviewed 2026-10-24
Destination profileSupabase documentation reviewed 2026-10-24
Documentation date
Review window
Evidence3 sources
This route needs review.Use it as a planning baseline, then verify the dated sources and test with representative data before production.
Before you migrate

Should you make this move?

Both platforms have a case. Compare what you gain with what you give up before scheduling the cutover.

Current platform

PostgreSQL

Reasons to stay
  • Powerful SQL, extensions, integrity, and open governance support demanding workloads
  • A mature data model and query ecosystem supports serious production workloads
Reasons to leave
  • Tuning, upgrades, and sophisticated features require experienced operators
  • Schema design, migration, tuning, and operations require specialist attention
New platform

Supabase

What gets better
  • PostgreSQL, authentication, storage, realtime, and edge functions offer an open backend stack
  • Managed infrastructure removes a large amount of operational work
What gets worse
  • Production scaling and service integration still demand database and infrastructure judgment
  • Platform-specific services can create architectural lock-in
Best of the move

Supabase: PostgreSQL, authentication, storage, realtime, and edge functions offer an open backend stack. This removes a major source-side concern: Tuning, upgrades, and sophisticated features require experienced operators.

Worst of the move

What you lose: Powerful SQL, extensions, integrity, and open governance support demanding workloads. What you inherit: Production scaling and service integration still demand database and infrastructure judgment.

Jump to a section
01At a glance

Know the shape of the move.

Transfer outcome12 features audited
Transfer outcome distributionClean transfer: 0, Partial transfer: 7, Manual rebuild: 2, Not transferred: 3.
Clean0
Partial7
Manual2
Lost3
Mapping route8 of 9 fields have a destination path

This timeline assumes

  • Up to 500 GB of Postgres data, 200 tables, and 100,000 application users
  • Application and data owners approve a target version, extension list, role model, and RLS plan.
  • A production-shaped snapshot and write workload are available for rehearsal.
  • PostgreSQL remains authoritative until lag reaches zero and all invariants pass.
  • The migration team records evidence for every blocking verification check.
02What transfers

What survives the move.

“Partial” and “manual” are not footnotes. They are work that must be scheduled and verified.

ItemOutcomeImpactWhat happensMitigation
Schemas, tables, and row datapartialcriticalSupabase documents dump/restore for all versions and logical replication for Postgres 10+. The dump should use directory format with --no-owner, --no-privileges, and --no-subscriptions. Restore through session-mode pooling or a direct connection, not transaction mode.Rehearse on a matching compute size, then compare row counts after VACUUM ANALYZE.
Postgres major versionpartialcriticalSupabase calls downgrade migrations highly not recommended. A custom-format dump from a newer server can fail restore on an older target because pg_restore rejects a newer file header.Match versions before dump, or use a method that converts types instead of restoring a newer custom dump.
Users, roles, and privilegeslostcriticalSupabase does not migrate users or roles with the dump. --no-owner and --no-privileges are applied so source owners do not collide with the managed project.Recreate required roles and grants after import and test every application login.
Row Level Security statuslostcriticalSupabase states that RLS status on tables is not migrated. Policies you later enable will deny rows that the old application could read.Enable RLS only after grants exist, then test each role against real identities.
ExtensionspartialhighSource extensions must exist in pg_available_extensions on Supabase and be created before restore. Supabase also ships extensions such as pg_graphql and pgcrypto that a Prisma or migration history may treat as drift.Compare extension lists, install what you need, and mark managed extensions as already applied in your migrator.
Logical replication gapspartialcriticalReplication does not copy DDL, sequences, or large objects. Every table that receives UPDATE or DELETE needs a replica identity, usually a primary key.Freeze schema, set replica identity, sync sequences at freeze, and copy LOBs separately.
Connection poolingmanualcriticalSupabase exposes direct, session, and transaction pooler modes. Migration tasks need session mode on port 5432. Transaction-mode poolers on port 6543 can fail schema migrations and prepared statements.Use session or direct URLs for dump, restore, and migrators, then point the app at the approved pooler.
Indexes, planner statistics, and query timepartialhighA restore does not leave the planner in the same state as the source. Supabase tells you to run VACUUM ANALYZE after import.Rebuild needed indexes and benchmark production-shaped queries before cutover.
Auth, Storage, Realtime, and Edge FunctionsmanualhighA Postgres dump does not create Supabase Auth users, storage buckets, or functions. Those products stay empty until you add them.Inventory each adjacent service and approve a replacement or an exclusion.
Subscriptions and source-only objectslostmediumSupabase asks you to dump with --no-subscriptions because source logical subscriptions will not work on the target.Recreate any required publication or subscription on Supabase after cutover.
Compute and restore capacitypartialhighSupabase publishes VM and compute sizes by database size and asks you to contact support before starting above 150 GB, or for custom sizing above 1 TB.Upgrade compute before a large restore and size the migration VM in the same region.
In-flight writes and sequencespartialcriticalA dump taken while writers stay open misses later rows. Logical replication still needs a sequence sync after freeze.Set the source read-only for production cutover, sync sequences, then switch clients.
03Field and feature mapping

Where each thing goes.

SourceDestinationMethodNotes
PostgreSQL cluster or databaseSupabase project and Postgres databasemanualRecord region, version, and session-mode URL.
Schema and tableMatching schema and tabletransformDump with --no-owner and --no-privileges.
Role, owner, or grantRecreated Supabase role and grantmanualDo not expect the dump to create source users.
Primary key or replica identityPrimary key or REPLICA IDENTITY FULLtransformRequired before logical replication of updates.
SequenceSequence value after freezemanualDump sequence data after the source is read-only.
ExtensionCREATE EXTENSION on SupabasemanualInstall only names listed in pg_available_extensions.
RLS flag or policyEnabled RLS and tested policymanualRe-enable after grants, then test denied paths.
Application DATABASE_URLDirect or session pooler URLmanualKeep migrators off transaction mode on port 6543.
Logical subscriptionNone during dump, then a new subscription if neededunsupportedSource subscriptions are excluded from the dump.
04Before you begin

Make the move recoverable.

Backup procedure

Create the source-of-truth backup

Preserve PostgreSQL data, configuration, and operating evidence before any destination write.

  1. Create a native, restorable PostgreSQL backup plus a directory-format dump with --no-owner and --no-privileges.
  2. Inventory schemas, extensions, roles, sequences, replica identities, RLS, jobs, and integrations.
  3. Record counts, checksums, sizes, lag, query times, and recovery baselines.
  4. Hash all immutable backup and migration artifacts.

Proof to capture: A signed manifest reconciles every scoped record class, runtime dependency, export file, count, and hash.

Transformation · pg_dump inventory, pg_available_extensions, and role workbook

Version, extension, and role map

Decide dump versus logical replication and list objects the dump will not create.

  1. Compare source version and extensions with the Supabase project.
  2. List roles, grants, RLS flags, sequences, and LOBs as manual work.
  3. Reject unmapped critical records.

Proof to capture: Save the input, output, command or tool settings, warnings, and final item counts.

Transformation · pg_dump/pg_restore or publication/subscription, then verification SQL

Repeatable restore or replication pipeline

Load schema and data, catch up writes, and cut over deterministically.

  1. Restore through session mode or a direct URL.
  2. Run VACUUM ANALYZE and compare row counts.
  3. Reconcile accepted, rejected, and transformed objects.

Proof to capture: Save the input, output, command or tool settings, warnings, and final item counts.

05Handle with care

The things most likely to hurt.

These are operating limits. Treat every “Stop if” condition as a blocked migration, not a suggestion.

Transform

A newer dump will not restore

criticalpossible likelihood

pg_restore rejects a custom dump whose file header is newer than the target server.

Consequence
The rehearsal fails after the source was already frozen, or production stays on the old host.
Mitigation
Match versions, or prove a conversion path that is not a newer custom dump.

Stop if: The target cannot restore a representative dump.

Security

Authorization is weaker or stricter than the source

criticalpossible likelihood

Missing grants look like broken RLS, and newly enabled RLS hides rows the app still needs.

Consequence
Users see empty screens or read another tenant’s rows.
Mitigation
Recreate grants first, then enable RLS and test every role.

Stop if: Any unauthorized operation succeeds or a required read returns no rows.

Cutover

Final delta misses writes or sequences

criticalpossible likelihood

Writers stay open, replication lags, or sequences are not synced after freeze.

Consequence
Primary keys collide or source and destination diverge.
Mitigation
Set the source read-only, wait for zero lag, and import sequence values.

Stop if: Lag is nonzero or an unexplained delta exists.

06Precise timeline

Do the work in this order.

Estimate forUp to 500 GB of Postgres data, 200 tables, and 100,000 application users
Total elapsed10–25 business days
Active work40–90 hours
BufferAdd time for a version downgrade, databases above 150 GB, missing primary keys, large objects, or a strict zero-downtime cutover.
01
Days 1–3Inventory and decisions2–3 days
02
Days 3–6Backup and reconcile2–4 days
03
Days 6–16Map and pilot5–10 days
04
Days 14–22Final delta and switch1–4 days
05
Days 16–35Observe and close4–10 days
  1. Days 1–3 · inventory

    Inventory and decisions

    6–12 hours active2–3 days elapsedOwner review waiting
    • Inventory PostgreSQL version, extensions, roles, sequences, and integrations.
    • Approve dump versus logical replication and the RLS plan.

    Depends on: PostgreSQL and Supabase administrator access

    Stop / go checkpoint

    Export?

    Go when: Every critical item has an owner and disposition.

    Stop when: Consent, billing, access, or system ownership is unclear.

  2. Days 3–6 · backup

    Backup and reconcile

    6–14 hours active2–4 days elapsedDump processing waiting
    • Create a native backup and a directory-format dump.
    • Reconcile counts, totals, and hashes.

    Depends on: Approved inventory

    Stop / go checkpoint

    Transform?

    Go when: Source totals and export manifests agree.

    Stop when: Any critical dataset or configuration is absent.

  3. Days 6–16 · pilot

    Map and pilot

    16–45 hours active5–10 days elapsedDestination processing and review waiting
    • Restore or replicate into a rehearsal Supabase project.
    • Recreate roles, grants, and RLS, then run application queries.

    Depends on: Verified backup

    Stop / go checkpoint

    Scale?

    Go when: Pilot mappings, behavior, access, and evidence pass.

    Stop when: Any critical check fails or produces unexplained variance.

  4. Days 14–22 · cutover

    Final delta and switch

    6–20 hours active1–4 days elapsedReplication drain or final restore waiting
    • Freeze production writes in PostgreSQL.
    • Apply the final delta, switch clients, and run blocking checks.

    Depends on: Passed pilot and approved rollback

    Stop / go checkpoint

    Open production?

    Go when: Counts reconcile and one destination system owns production.

    Stop when: A source writer remains active or a blocking check fails.

  5. Days 16–35 · observe

    Observe and close

    4–16 hours active4–10 days elapsedOperating-cycle evidence waiting
    • Monitor one complete operating cycle.
    • Sign the verification report and close rollback only after stability.

    Depends on: Verified cutover

    Stop / go checkpoint

    Close rollback?

    Go when: No trigger occurs during the agreed observation period.

    Stop when: Data, access, delivery, routing, or business results regress.

07The point of change

Cut over with a way back.

Go live

Cutover

Make Supabase the only production system without losing the final PostgreSQL delta.

Recommended window: A low-volume weekday morning with platform, data, and application owners available.

  1. Freeze production writes and scheduled actions in PostgreSQL.
  2. Finish restore or drop the subscription after zero lag, then sync sequences.
  3. Point application clients at the approved Supabase URL.
  4. Run every blocking verification check and keep PostgreSQL intact.
  5. Leave the source read-only so writers cannot create a split brain.

Proof to capture: Supabase owns production, totals reconcile, and every blocking check has durable evidence.

Return to safety

Rollback

Return production ownership to PostgreSQL without losing destination-era changes.

Deadline: Within seven days and before source data, plans, credentials, domains, or billing are changed.

  1. Stop new writes and scheduled actions in Supabase.
  2. Restore the prior PostgreSQL routing, jobs, and client configuration.
  3. Export the Supabase post-cutover delta.
  4. Review and apply safe destination-era changes to PostgreSQL.
  5. Run the same blocking checks against the restored source.

Proof to capture: PostgreSQL again owns production with current data and no duplicate destination action.

Rollback immediately when
  • Unexplained critical count or value variance
  • Missing or exposed critical data
  • Failed access, routing, delivery, or integration check
  • Primary-key collisions after sequence drift
  • A critical feature has no safe destination replacement
08Verification report

Prove the migration worked.

Every blocking check must pass. Capture the evidence before cleanup begins.

0%
Interactive report preview0 / 8 checks passed
PassIDCheckMethodExpected resultEvidence
V-01BlockingRecord reconciliationCompare counts, checksums, aggregates, and stratified records.Every scoped record is accounted for.Data ledger.
V-02BlockingTypes and extensionsCompare tables, constraints, and pg_extension with the signed inventory.Required objects exist and unneeded source owners are absent.Schema report.
V-03BlockingRoles and application loginTest each recreated role and application connection string.Approved users connect and unknown roles are rejected.Access log.
V-04BlockingReference and sequence integrityQuery parents, children, orphans, and next sequence values.Every critical invariant holds.Integrity report.
V-05BlockingGrants and RLSRun allowed and denied operations for every role.Least privilege matches policy.Access evidence.
V-06BlockingFunctional and performance parityRun production-shaped reads and writes after VACUUM ANALYZE.Results and service objectives pass.Benchmark report.
V-07BlockingBackup, restore, and rollbackRestore a destination backup and execute the rollback rehearsal.Recovery objectives and integrity pass.Recovery report.
V-08BlockingWrite authorityInspect writers, jobs, APIs, and application connections.Supabase alone accepts approved writes with zero unexplained delta.Cutover checklist.
09Post-migration cleanup

Remove the scaffolding safely.

Safe after: One complete operating cycle, at least seven stable days, and owner sign-off on every blocking check.

  1. Create final PostgreSQL exports and archive verification evidence.
  2. Revoke temporary credentials, API keys, replication slots, and elevated roles.
  3. Remove obsolete publications, jobs, integrations, and unused connection strings.
  4. Keep the source intact through the approved retention window.
  5. Cancel paid plans only after billing, legal, and recovery review.
  6. Schedule the next Supabase backup, access, and migration-playbook review.
10Experiences from the field

When the plan met reality.

First-hand accounts are preferred. Vendor case studies are labeled, and every note below is an editorial paraphrase—follow the link for the full context.

First-person accounthalfmoon.day

Migrating a Database from PostgreSQL on Docker to Supabase2025

The author moved a PostgreSQL 17 database running in Docker on EC2 to Supabase, which was then on PostgreSQL 15, to cut EC2 memory use and stop keeping the database on the same instance as the app. A custom-format pg_dump failed restore because pg_restore rejected file header version 1.16. Plain SQL dumps then broke on \N copy syntax and UUID handling. Supabase CLI push also failed on the version gap. A DBeaver table transfer finally moved schema and data across the downgrade.

What they recommend
  • Check the source and Supabase major versions before you take a custom-format dump, because a newer file header will not restore.
  • Rehearse the restore on a throwaway project and keep a conversion path ready if the versions do not match.
Worth noticing
  • PostgreSQL restore compatibility does not go backwards, so a PG17 custom dump is the wrong artifact for an older target.
  • The successful path here was a tool that converted tables, not a one-shot pg_restore of a newer backup.
First-person accountslowhand · Zenn

Migrating from Prisma + PostgreSQL to Supabase: Errors and Solutions2025

slowhand pointed an existing Prisma 6.8.2 PostgreSQL app at Supabase and hit drift because the project already contained extensions such as pg_graphql, pg_net, pgcrypto, and uuid-ossp. The fix was a 0_init migration that created those extensions, then prisma migrate resolve --applied. A later Cloud Build migrate against the transaction pooler on port 6543 failed to reach the database until the private Cloud Build pool setting was removed. The write-up is about schema tooling, not a full data cutover.

What they recommend
  • Inventory Supabase’s preinstalled extensions and mark them applied in Prisma before you run migrate dev.
  • Use a session or direct database URL for schema migrations, and keep transaction-mode port 6543 for the app only after migrators pass.
Worth noticing
  • Supabase is Postgres plus extensions and pooling, so a working schema.prisma can still fail on first connect.
  • A Cloud Build networking pool can look like a Supabase outage when the URL is otherwise correct.
Sources and evidence

Verify against the primary material.

Platform behavior changes. Check these sources and the review dates above before executing a production migration.

  1. Supabase: migrate from PostgresAccessed 2026-10-24
  2. PostgreSQL: pg_dumpAccessed 2026-10-24
  3. PostgreSQL: SQL dump backupsAccessed 2026-10-24