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.
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.
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.
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.
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.
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.
Four Heroku guardrails change how the move behaves. They are cheaper to handle in planning than mid-cutover.
\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.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.
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.
Write the steps down, rehearse them on a staging copy, and decide the rollback before you touch production.
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.
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.
| Funding | Who files it | Amount | When 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 Founders | Founder applies | $1,000 to start, up to $5,000 | Self-funded startups with no investor or accelerator behind them. |
| AWS Activate Portfolio | Founder applies | up to $200,000 | Startups backed by a VC firm, accelerator or angel investor that is an AWS Activate Provider. |
Pick the method your Heroku plan allows, then check the downtime against your window.
| Method | Heroku plans | Downtime | Notes |
|---|---|---|---|
| pg_dump and pg_restore | All plans | Full dump plus restore (measure it) | Simplest; writes must really be frozen |
| Managed logical replication | Heroku Postgres Advanced only | Short pause to drain changes and repoint | DDL and sequences do not replicate; tables need a primary key |
| AWS DMS full load | All plans (no CDC on classic plans) | Full load time (writes frozen) | Managed copy with row validation |
You fill in a short form: what you run today, what you want to move, test or build, your stage and your region.
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.
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.
If the work qualifies, the partner files the funding request with AWS. AWS reviews it and decides. The amount depends on the workload.
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.
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.