heroku postgres → rds · 2026 cutover guide

Heroku Postgres to RDS: pick the method, run the cutover, size the downtime.

On most Heroku Postgres plans you cannot stream changes to AWS, because Heroku does not grant the replication role that AWS DMS or logical replication needs. So the default path is pg_dump and pg_restore inside a planned write freeze. Heroku Postgres Advanced is the exception: it supports managed logical replication to an external database, which makes a short cutover possible.

default method
pg_dump + pg_restore
short-window option
Advanced tier only
the switch
one DATABASE_URL change
TL;DR
  • Heroku does not let you grant the replication role on Essential, Standard or Premium plans, so AWS DMS change data capture and native logical replication to RDS are not available there. You freeze writes, run pg_dump into pg_restore, verify, and repoint the app. Downtime equals the time that takes, so measure it on a copy first.
  • If you are on Heroku Postgres Advanced, Heroku's managed logical replication can stream changes into RDS or Aurora while the app keeps running. Cutover is then a short pause to drain changes, fix sequences and swap DATABASE_URL.
  • Plan for the Heroku specifics: followers, connection limits, pinned extensions and forced SSL. The database move is usually part of a wider Heroku to AWS migration, and that wider migration is what can qualify for partner-filed MAP funding: typically $50K to $150K for startups. Depends on the workload; AWS approves.
what your plan allows

IThe cutover methods, and which Heroku plans allow them

Your Heroku plan decides your options more than your database size does. Start by checking which tier you are on.

Heroku states that it does not give customers the superuser role or let them grant the replication role. Tools that stream changes, such as AWS DMS with change data capture (CDC), need that role. So on classic plans a near-zero-downtime stream to AWS is off the table.

Method 1: pg_dump and pg_restore (any plan)

How it works: put the app in maintenance mode so writes stop, dump Heroku Postgres in custom format, restore into RDS, verify, then bring the app up on RDS. A common one-liner is pg_dump $HEROKU_DATABASE_URL -Fc | pg_restore --no-owner --no-acl -d $RDS_DATABASE_URL. The --no-owner and --no-acl flags matter because Heroku owns the source roles.

Downtime: the whole dump plus restore, because writes are frozen throughout. Index rebuilds usually dominate restore time. The only reliable number is one you measure on a throwaway RDS instance.

Watch out for: maintenance mode must really block writes, or anything written after the dump starts is lost. Restore on a larger instance and size it down afterwards.

Method 2: managed logical replication (Heroku Postgres Advanced only)

How it works: on Heroku Postgres Advanced you enable publishing, create a publication, mirror the schema to RDS with pg_dump --schema-only, then create a subscription on RDS with the publisher credentials. Postgres copies existing rows and then streams changes.

Downtime: a short pause at cutover to drain the last changes, advance sequences and swap DATABASE_URL. The bulk copy happens while the app is live.

Watch out for: schema changes (DDL) and sequence values do not replicate. Freeze schema changes during the migration and use setval() at cutover. Tables need a primary key or unique index to replicate updates and deletes.

Where AWS DMS fits

AWS DMS can still do a full load from Heroku Postgres with a normal user, which is a managed alternative to pg_dump with built-in row validation. It cannot do ongoing CDC from a classic Heroku plan, so writes still have to be frozen during the load.

the decision rule

On Essential, Standard or Premium: pg_dump and pg_restore in a measured maintenance window. On Advanced: managed logical replication for a short cutover. If the window is too long on a classic plan, ask whether moving to Advanced first is worth it.

what bites you

IIHeroku Postgres specifics to plan for

Four Heroku guardrails change how the move behaves. They are cheaper to handle in planning than mid-cutover.

  • Follower databases: Followers are Heroku read replicas. They do not migrate themselves. List every follower and what reads from it (reports, search indexing, read-heavy endpoints), create an RDS read replica or Aurora reader to match, and repoint those readers in the same cutover.
  • Connection limits: Heroku caps connections by plan: 20 on Essential-0 and Essential-1, 40 on Essential-2, 200 on Standard-0 and Premium-0, and 500 on larger plans (Heroku plans page). On RDS, max_connections scales with instance memory, and Amazon RDS Proxy gives managed pooling. Decide whether you keep PgBouncer or adopt RDS Proxy.
  • Pinned extensions: Run \dx on the source to list installed extensions (often pg_stat_statements, citext, uuid-ossp or pgcrypto, hstore, sometimes PostGIS). Create each one on RDS before the restore and check versions.
  • Forced SSL and roles: Heroku requires SSL. Enforce it on RDS too (rds.force_ssl) and ship the RDS CA bundle so sslmode=verify-full works. Dump with --no-owner --no-acl and create your own application role on RDS.
the actual switch

IIIThe DATABASE_URL swap

After all the preparation, production moves with one config change. Know how Heroku sets it so it does not revert.

The Postgres add-on is attached to the app, and that attachment sets DATABASE_URL. Heroku can rotate those credentials, so if you only overwrite the value while the add-on is still attached, a later rotation can point the app back at Heroku Postgres. Detach the add-on from DATABASE_URL at cutover.

Most frameworks read DATABASE_URL at boot, so the change needs a restart. Do one coordinated restart inside the maintenance window. Writes split across two databases are the worst cutover failure, and a single restart prevents them.

choosing the target

IVRDS for PostgreSQL or Aurora PostgreSQL

Both are managed PostgreSQL on AWS, and the migration steps are the same for either.

RDS for PostgreSQL is the like-for-like choice: you pick the version, instance class, storage (gp3 is a sensible default) and Multi-AZ. It is the closest match to Heroku Postgres, and you can move to Aurora later.

Aurora PostgreSQL uses a distributed storage layer: storage grows on its own, failover is usually faster, and you can add up to 15 readers. It costs a bit more. It suits apps that already lean on followers for reads or expect fast data growth.

the runbook

VThe cutover runbook, with a rollback

Write the steps down, rehearse them on a staging copy, and decide the rollback before you touch production.

  • Before: provision RDS or Aurora, create extensions, size connections and storage, enforce SSL, and create replicas to match your followers.
  • Rehearse: restore a recent dump (or run the replication on Advanced) into a staging target and time it. That measured time, plus margin, is your window.
  • Cutover: turn on maintenance mode so writes stop. Run pg_dump into pg_restore, or on Advanced wait for the subscription to catch up and stop it.
  • Reconcile: advance sequences with setval(), check row counts on the biggest tables, and check key constraints.
  • Switch: set DATABASE_URL to the RDS endpoint (sslmode=verify-full plus the CA), detach the Heroku attachment, and restart all processes together.
  • Verify: smoke test a read, a write, a typical transaction and a background job. If green, turn maintenance mode off.
  • After: keep the Heroku database read-only for a few days as a fallback, watch RDS connections, CPU and slow queries, and size the instance down.
rollback rule

Rollback is cheap only before the app writes to RDS: revert DATABASE_URL and restart. After writes land on RDS, switching back loses them unless you built reverse replication in advance. The smoke test before you leave maintenance mode is the real decision point.

who runs it, who funds it

VIWho runs the cutover, and who can fund it

You can run this yourself with the steps above. Many teams prefer someone who has done it before to own the runbook, the validation and the early-morning switch.

A vetted AWS partner can provision the target, pick the method your Heroku plan allows, rehearse the runbook, run the cutover in your window and own the rollback decision.

Partner-filed funding: a database move on its own is usually small. It most often counts as part of the wider Heroku to AWS migration (app, database and supporting services). Your matched partner can file MAP funding for that migration when it qualifies and AWS approves. For startups this is typically $50K to $150K. Depends on the workload; AWS approves.

CloudRoute is free for startups. Partners pay CloudRoute a monthly membership plus 10% of AWS-approved funding.

Who files it
FundingWho files itAmountWhen it fits
Migration Acceleration Program (MAP)Your matched AWS partner$50K to $150K for startups. Depends on the workload; AWS approves.You are not on AWS yet and want to migrate.
AWS Activate FoundersFounder applies$1,000 to start, up to $5,000Self-funded startups with no investor or accelerator behind them.
AWS Activate PortfolioFounder appliesup to $200,000Startups backed by a VC firm, accelerator or angel investor that is an AWS Activate Provider.
Facts checked on October 10, 2026. AWS decides every application.
method comparison

pg_dump/restore vs managed logical replication vs DMS full load

Pick the method your Heroku plan allows, then check the downtime against your window.

MethodHeroku plansDowntimeNotes
pg_dump and pg_restoreAll plansFull dump plus restore (measure it)Simplest; writes must really be frozen
Managed logical replicationHeroku Postgres Advanced onlyShort pause to drain changes and repointDDL and sequences do not replicate; tables need a primary key
AWS DMS full loadAll plans (no CDC on classic plans)Full load time (writes frozen)Managed copy with row validation
Whatever the method, the production switch is the same: point DATABASE_URL at RDS and detach the Heroku attachment so it cannot be overwritten.
not sure which method your plan allows?
Get matched with a partner who runs the Postgres cutover for you
Get matched free with a vetted AWS partner who can file it
how a match works

How a match works (example)

  1. You tell us about the work

    You fill in a short form: what you run today, what you want to move, test or build, your stage and your region.

  2. We pick one partner

    We read your answers and pick one vetted AWS consulting partner that fits the work, the stack and the region. We reply within 24 hours; your matched partner reaches out within 5 business days.

  3. The partner checks MAP funding

    Your matched partner scopes the migration with you. Then it checks whether the move qualifies for MAP (Migration Acceleration Program) funding. MAP is for teams that are not on AWS yet.

  4. The partner files, AWS decides

    If the work qualifies, the partner files the funding request with AWS. AWS reviews it and decides. The amount depends on the workload.

  5. You pay nothing

    CloudRoute is free for startups. Partners pay CloudRoute a monthly membership plus 10% of AWS-approved funding.

AWS Activate credits are separate, and you apply for them yourself. Use Activate Founders if no investor backs you. Use Activate Portfolio with the Org ID or invite from your VC, accelerator, incubator or angel group if it is an Activate Provider. A consulting partner cannot apply for Activate on your behalf.

faq

Common questions

Can I migrate Heroku Postgres to RDS with near-zero downtime?
Only on Heroku Postgres Advanced, which supports managed logical replication to an external database. On Essential, Standard and Premium plans Heroku does not grant the replication role that AWS DMS CDC or logical replication needs, so you freeze writes and use pg_dump and pg_restore. Measure that time on a copy to size your window.
Can I use AWS DMS to migrate from Heroku Postgres?
For a full load, yes, with a normal database user. For ongoing change data capture, no, on classic plans: Heroku says third-party tools such as AWS DMS cannot replicate Heroku Postgres to a non-Heroku database because it does not grant the replication role. So a DMS full load still needs a write freeze.
Should I migrate to RDS for PostgreSQL or Aurora PostgreSQL?
RDS for PostgreSQL is the like-for-like choice and the simplest place to start. Aurora PostgreSQL adds storage that grows on its own, usually faster failover and up to 15 readers, at a higher price. The migration steps are the same for both.
What about my Heroku follower databases?
They do not migrate themselves. List every follower and what reads from it, create an RDS read replica or Aurora reader to match, and repoint those readers during the cutover. A forgotten follower means a report that keeps reading the old database.
How do I handle connection limits and pooling?
Heroku caps connections by plan: 20 to 40 on Essential plans, 200 on Standard-0 and Premium-0, 500 on larger plans. On RDS, max_connections scales with instance memory, and RDS Proxy gives managed pooling. Decide whether to keep PgBouncer or adopt RDS Proxy before the cutover.
Can I roll back if the cutover goes wrong?
Cheaply, only before the app writes to RDS: revert DATABASE_URL and restart. After writes land on RDS, switching back loses them unless you set up reverse replication in advance. Keep the Heroku database read-only for a few days as a fallback.
Can AWS fund the database migration?
A database move alone is usually small. As part of a wider Heroku to AWS migration, your matched AWS partner can file MAP funding when the migration qualifies and AWS approves. For startups this is typically $50K to $150K. Depends on the workload; AWS approves. CloudRoute is free for startups; partners pay CloudRoute.

Want a partner to run the Heroku Postgres to RDS cutover?

CloudRoute matches you with one vetted AWS partner who picks the method your plan allows, rehearses the runbook and owns the switch. When the wider migration qualifies, the partner files MAP funding and AWS decides. CloudRoute is free for startups.

we reply within24 hours
partner-filed funding$50K to $150K
CloudRoute fee for startups$0