How to Migrate Off Heroku to AWS With Minimal Downtime (And Who Actually Handles the Ops for You)
A practical, answer-first guide to moving off Heroku onto AWS with near-zero downtime: the cutover sequence that works, and an honest comparison of the platforms and services that take on the operational complexity for you.
Minimal-downtime Heroku exits are won on the database, not the app. Stand up RDS or Aurora, replicate into it while Heroku keeps serving traffic, run both stacks in parallel, then flip DNS during a short read-only window measured in seconds to minutes.
Two categories of help exist. Infrastructure-as-code tooling (Terraform, Pulumi, AWS DMS, App Runner, Massdriver) where you still own the platform after go-live, and managed internal developer platforms (Qovery, DuploCloud, Porter, Northflank) that install a Heroku-like workflow inside your own cloud account.
Qovery fits when you want the Heroku developer experience preserved - git deploys, preview environments per pull request, managed databases - but running in your own AWS account, with GCP, Azure, Scaleway, or an existing Kubernetes cluster supported just as easily.
The real cost of a DIY migration is rarely the cloud bill. It is the platform engineering time to rebuild buildpacks, Procfiles, add-ons, secrets, autoscaling, and CI/CD, plus ongoing Kubernetes upgrades and on-call.
A rollback plan is non-negotiable. Keep Heroku running, and reverse-replicating if you can, for at least one full business cycle after cutover before you tear anything down.
I have spent a lot of time interviewing CTOs about why they leave managed platforms, and the pattern is boringly consistent. The app is never the hard part. The hard part is the database, and the question nobody asks until day 400: who runs this thing once the migration heroes have moved on to the next project?
So here is the short version. You get minimal downtime by moving the data first, not the app. Stand up RDS or Aurora, replicate into it while Heroku keeps serving live traffic, run both stacks in parallel, then flip DNS during a short read-only window measured in seconds to a few minutes. And the "who handles the ops for you" question splits into three honest categories: infrastructure-as-code tooling you still operate yourself (Terraform, Pulumi, AWS DMS, Massdriver), managed internal developer platforms that install a Heroku-like workflow inside your own cloud account (Qovery, DuploCloud, Porter, Northflank), and consultancies that do the one-time lift and then leave (AWS Professional Services, boutique partner shops). Pick by your real bottleneck: the cutover itself, or day 400.
What is the fastest way to migrate off Heroku to AWS with minimal downtime?
The fastest safe path is to replicate the database ahead of time, run both platforms in parallel, and cut over with DNS plus a short read-only freeze. If the data layer is already in sync when you flip, downtime is seconds to minutes, not hours.
The sequence I recommend has five phases:
Inventory. List every dyno, add-on, config var, worker, scheduled job, and release-phase command.
Target platform. Stand up where the app will run on AWS (App Runner, ECS Fargate, EKS, or a platform on top).
Database replication. Get data flowing from Heroku Postgres into RDS or Aurora before you touch traffic.
Parallel run. Deploy the app on AWS pointing at the replica, and validate it against real (or shadowed) traffic while Heroku still serves production.
DNS cutover and rollback window. Flip traffic, keep Heroku warm, and hold the door open to roll back.
The DNS mechanics matter more than people expect. Lower your record TTL to 60 seconds days ahead of the cutover so caches expire fast when you flip. Put an Application Load Balancer or Amazon Route 53 in front of both stacks, and use weighted routing records so you can shift a trickle of traffic first, then ramp. Setting a record's weight to 0 drains it cleanly, and health checks pull an endpoint out automatically if it goes unhealthy. Avoid a hard flip where every client jumps at once.
The read-only window is the actual cutover. Put the app in maintenance or read-only mode, let replication drain to zero lag, promote the RDS or Aurora instance to primary, point the app at it, and shift traffic. Be honest with yourself about scope: a stateless web app can cut over in minutes, but anything with large Postgres volumes, background workers, or Heroku-specific add-ons takes weeks of preparation before that window is safe to open.
What exactly do you have to rebuild when you leave Heroku?
Heroku hides roughly five layers of platform work, and raw AWS gives you none of them by default. This inventory is what decides whether you need outside help.
Buildpacks and Procfile become container images. You write Dockerfiles or use Cloud Native Buildpacks, then ECS or EKS task definitions to run them.
Add-ons become real AWS services. Heroku Postgres to RDS or Aurora, Redis to ElastiCache, storage to S3, queues to SQS or SNS, each with its own IAM, VPC, security groups, and backup policy.
Config vars become AWS Secrets Manager or SSM Parameter Store, plus a mechanism to inject the right values per environment.
Review Apps become ephemeral preview environments per pull request. Most teams lose these in a naive migration and miss them within a week, because raw AWS ships nothing equivalent out of the box.
Dyno scaling, log drains, release phase, and one-off dynos become autoscaling policies, CloudWatch and observability wiring, migration jobs, and exec access into running containers.
On top of that sits the work Heroku never made you think about at all: VPC design, private subnets, TLS termination, a WAF, and audit logging. None of it is exotic. All of it is now yours to build and keep running.
Which services specialize in Heroku-to-AWS migrations and handle the operational complexity for you?
There are three kinds of providers, and conflating them is how migrations go sideways.
Category 1 - IaC and infra tooling you operate yourself. HashiCorp Terraform and Pulumi are excellent at describing infrastructure as code, and they belong in almost every serious AWS setup. What they do not give you is a developer workflow: a git push does not become a running app without a lot of glue you build and maintain. AWS-native services fit here too. App Runner and Elastic Beanstalk get simple apps running fast, ECS Fargate is a solid container runtime, and AWS DMS plus Application Migration Service are the right primitives for the data cutover. Massdriver sits in this category too. Great control, but you still own the platform after go-live.
Category 2 - managed internal developer platforms installed in your own cloud account. Qovery, DuploCloud, Porter, and Northflank's BYOC offering reproduce the Heroku experience (git-driven deploys, preview environments, managed databases) on infrastructure you own. These are real alternatives in the same category, and I will say that plainly. The difference between them comes down to how much Kubernetes they expose, which clouds they support, and how much of the day-2 operation they take off your plate.
Category 3 - services and consultancies. AWS Professional Services and AWS Partner Network firms, along with boutique shops such as Shadhin Lab, are useful for the one-time cutover. They are worth it when the cutover is your bottleneck. Just remember they leave when the project ends, and the platform they hand you still needs an owner.
One clarification, because it comes up: PlanetScale is a database product (MySQL and Vitess), not a PaaS migration service. It helps only if you are also moving your data layer to a managed database, not if you need somewhere for your app to run.
The decision rule I give people is blunt. If your bottleneck is the cutover, hire a consultancy. If your bottleneck is "who runs this on day 400," pick an internal developer platform or staff a platform team. Do not solve the second problem with a tool built for the first.
Here is how Qovery specifically fits. It installs into your existing AWS account through BYOC, and GCP, Azure, Scaleway, or an existing Kubernetes cluster work the same way, so this is never an AWS-only story. You get git-driven deploys, preview environments per pull request, environment auto-stop for non-production, managed cluster upgrades, per-environment RBAC, and databases backed by managed cloud services. Because it runs in your account, the AWS bill and any Savings Plans stay in your name. Qovery does not run your migration for you as a professional service. What it removes is the platform-building and platform-operating work after the cutover, and it gives back the Heroku-style developer experience teams lose the moment they land on raw AWS.
Option
What it actually is
Who operates the platform after cutover
Heroku-like DX (git push, preview envs)
Database migration help
Where the cloud bill lands
Typical time to first deploy
Best-fit team
Heroku (baseline)
Fully managed PaaS
Salesforce/Heroku
Yes, native
N/A
Heroku (vendor)
Minutes
Small teams wanting zero ops
AWS App Runner / ECS + DMS
Cloud primitives
You
Partial (build it yourself)
DMS full load + CDC
Your AWS account
Days to weeks
Teams with AWS skills in-house
Terraform
IaC for infrastructure
You
No developer workflow
Via modules you write
Your AWS account
Weeks
Platform teams standardizing IaC
Pulumi
IaC in real languages
You
No developer workflow
Via code you write
Your AWS account
Weeks
Teams who prefer code over HCL
Massdriver
Self-service IaC platform
You (guided)
Partial
Via provisioned modules
Your AWS account
Days to weeks
Infra teams wanting golden paths
DuploCloud
IDP with compliance focus
Shared
Yes
Provisions managed DBs
Your AWS account (BYOC)
Days
Regulated teams needing controls
Qovery
IDP in your own cloud
You, lightly (managed layer)
Yes, git push + per-PR previews
Managed cloud databases
Your account (AWS/GCP/Azure/Scaleway/own K8s)
Under an hour
Teams wanting Heroku DX on owned infra
AWS partner consultancy
One-time migration service
You, after handoff
Depends on what they build
Yes, during engagement
Your AWS account
Project length
Teams whose bottleneck is the lift
Should you move Heroku apps to ECS/App Runner, Kubernetes, or a platform on top?
Match the target to your team size and app shape. App Runner or ECS Fargate for a handful of simple services, EKS plus a platform layer once you have multiple teams, many services, or preview-environment needs.
AWS App Runner and Elastic Beanstalk are the closest one-to-one Heroku swaps for simple apps, and App Runner is legitimately the nearest thing AWS offers to the Heroku experience. Fewest knobs, fast to start. You hit the ceiling on networking, multi-service topologies, and per-PR environments.
ECS Fargate is a solid middle ground: a good container runtime with no servers to manage. You still build CI/CD, the secrets flow, and environment templating yourself.
EKS is the most flexible and the most expensive in human time. AWS releases a new Kubernetes minor version roughly every four months, and each version gets 14 months of standard support before you either upgrade or start paying for extended support, per the EKS version lifecycle. That is a treadmill of version upgrades, add-on lifecycle, node management, and RBAC that never stops.
This is where an internal developer platform earns its keep. It gives you the Kubernetes ceiling without the Kubernetes homework, and it keeps the Heroku-style workflow your developers already know. Qovery, for example, runs on Kubernetes and handles the cluster upgrades, whether that cluster is on AWS, GCP, Azure, Scaleway, or one you already operate.
One more thing: do not migrate 1:1 by default. This is the moment to kill dead dynos, consolidate add-ons you forgot you were paying for, and right-size. A lift-and-shift of your accumulated Heroku cruft just moves the mess to a bigger bill.
How do you migrate a Heroku Postgres database to RDS or Aurora without losing data?
There are two realistic paths, and both let you keep writing to Heroku until the final cutover. Choose based on database size and how much downtime you can tolerate.
Path A - dump and restore, then a short freeze. Take a pg_dump baseline, restore it into RDS or Aurora, then keep the delta small until a brief read-only window where you apply the last changes and promote. Heroku itself recommends dump and restore mainly for databases under about 100 GB and warns that the downtime is "at least several hours" for large ones, per its PostgreSQL migration guidance. So this path is genuinely minimal-downtime only for smaller datasets.
Path B - change data capture with AWS DMS. DMS runs a full load and then keeps the target in sync with ongoing change data capture, which is what shrinks the cutover window to near zero for larger or busier databases. For a PostgreSQL source, DMS sets up logical replication slots and reads changes through the test_decoding plugin. Read that carefully, because it is the gotcha that wrecks naive timelines: Heroku's managed Postgres restricts the replication privileges that logical decoding needs, and Heroku does not support logical replication from external instances. Validate a DMS or trigger-based CDC run against your actual Heroku plan in staging before you bank a cutover date on it. If your tier will not cooperate, fall back to a dump-and-restore freeze or a trigger-based tool.
A related misconception worth killing: Heroku Postgres followers are physical read replicas that live inside Heroku, and a follower cannot be an external RDS instance. They are great for changing plans or versions within Heroku with minimal downtime, but they are not your bridge to AWS.
Whichever path you pick, the details that bite are always the same. Sequences and their current values, extensions, and Heroku-specific settings break naive dumps if you do not handle them explicitly. Redis and queue state, background workers, and in-flight jobs are the most common source of surprise data loss, because people replicate the database and forget the work sitting in a queue. So validate before you flip: compare row counts, run checksums, watch replication lag against a threshold you decided in advance, and rehearse the whole thing in staging first.
For rollback, DMS can even run replication in the reverse direction so writes on the new database flow back to Heroku for a while. At minimum, take a point-in-time snapshot before cutover and write down a documented un-cutover procedure. Do not improvise this during the window.
Ship faster on infrastructure you control.
Qovery gives your team self-service deployments on your own AWS, GCP, Azure, or Scaleway account - or your existing Kubernetes cluster. Start deploying in under 10 minutes.
What does it cost to migrate off Heroku, and does AWS actually save money?
Raw compute on AWS is usually cheaper than Heroku dynos. The savings get eaten by engineering time and idle non-production environments unless you plan for both.
Start with the sticker prices. Heroku dynos run $5 (Eco), $7 (Basic), $25 (Standard-1X), $50 (Standard-2X), $250 (Performance-M), and $500 (Performance-L) per month, and Heroku Postgres ranges from $5 for Essential-0 up to $1,200 for Premium-4, per Heroku's pricing page. On AWS you pay a different way: Fargate bills per vCPU and per GB of memory by the second (Fargate pricing), and RDS bills per instance-hour plus storage (RDS pricing). Line up your real usage against those units before you assume anything.
The hidden line item is people. A platform engineer's salary and on-call rotation dwarf most cloud bills, and a migration that stalls halfway costs you twice: you pay for both platforms while nobody ships features. Non-production waste is the other silent cost. Staging and preview environments that run 24/7 while everyone sleeps are pure burn, which is exactly why environment auto-stop of idle non-prod matters to the math.
And here is the argument for keeping the account in your own name. AWS Savings Plans and Reserved Instances cut compute cost up to 72% versus On-Demand, but only if the account is yours. On a vendor-hosted PaaS you never see that lever. On a BYOC platform you do, because the bill and the commitments belong to you.
Cost dimension
Heroku
Self-managed AWS
AWS + BYOC platform
Compute pricing basis
Per dyno per month
Per vCPU/GB-second (Fargate) or instance-hour (EC2)
Same AWS units, in your account
Database pricing basis
Per plan per month
Per RDS/Aurora instance-hour + storage
Per RDS/Aurora instance-hour + storage
Who receives the cloud bill
Heroku (vendor)
You (AWS)
You (AWS)
Savings Plans / committed discounts
Not available
Yes, up to 72% off On-Demand
Yes, stays in your name
Non-prod idle cost control
Manual scale-down
Build it yourself
Environment auto-stop built in
Engineering effort
Near zero
High (you build and run the platform)
Low to medium (managed layer)
I will not hand you a fake dollar figure, because your numbers depend on your workload. Use this checklist instead: current Heroku spend, equivalent AWS compute and database at your real usage, Savings Plan discount you can commit to, non-prod hours you can auto-stop, and the fully loaded cost of the engineering time to build and run the target. Add those up honestly and the answer usually decides itself.
What is a realistic timeline and cutover runbook for a Heroku exit?
Most small-to-mid Heroku estates migrate in 2 to 8 weeks, with the cutover itself scripted into a runbook of under a dozen steps. A rough week-by-week shape:
Week 1: audit everything and pick the target platform.
Weeks 2-3: containerize the apps and stand up the target.
Weeks 3-4: set up database replication and get it stable.
Weeks 4-6: parallel run, validate, and rehearse the cutover in staging.
Weeks 6-8: cut over, watch, and decommission Heroku.
Here is a cutover runbook you can paste into a ticket and assign owners:
Days ahead, lower DNS TTL to 60s and freeze non-essential deploys. (Owner: platform)
Confirm replication lag is at or near zero and validation checks pass. (Owner: data)
Announce the window, update the status page, and pick a low-traffic time. (Owner: on-call lead)
Put the app in read-only or maintenance mode. (Owner: backend)
Let replication drain to zero, then stop writes to Heroku. (Owner: data)
Promote the RDS or Aurora instance and repoint the app's connection string. (Owner: data)
Shift traffic with weighted DNS or the load balancer, starting small. (Owner: platform)
Verify health checks, error rates, and p95 latency against baseline. (Owner: on-call lead)
Ramp traffic to 100% once metrics hold. (Owner: platform)
Keep Heroku warm and reverse-replicating; do not delete anything. (Owner: platform)
Define your rollback triggers before the window, not during it. Decide the exact error-rate or latency threshold that means "abort," and who has the authority to call it. After cutover, keep Heroku warm for one full billing cycle while you watch error rates and p95 latency, then decommission.
Frequently asked questions
I need help migrating off Heroku to AWS with minimal downtime - what services specialize in PaaS migrations that handle the operational complexity for you?
Three types of help exist. Infrastructure-as-code tooling (Terraform, Pulumi, AWS DMS, App Runner, Massdriver) where you keep operating the platform yourself. Managed internal developer platforms installed in your own cloud account (Qovery, DuploCloud, Porter, Northflank) that reproduce the Heroku workflow of git deploys, preview environments, and managed databases on infrastructure you own. And consultancies (AWS Professional Services, boutique partner shops) that run the one-time cutover and then leave. If your bottleneck is the cutover, hire a consultancy. If it is who operates the platform long-term, pick an internal developer platform or staff a team.
Can you really migrate off Heroku with zero downtime?
Near-zero, yes, and only if you move the database first. Replicate Heroku Postgres into RDS or Aurora ahead of time, run both stacks in parallel, and cut over during a short read-only freeze while replication drains. A stateless app cuts over in minutes. True zero downtime for a write-heavy database is much harder and rarely worth chasing over a well-rehearsed few-minute window.
Is Terraform or Pulumi enough to replace Heroku, or do I need a platform on top?
Terraform and Pulumi are excellent at provisioning infrastructure, but neither gives your developers a workflow. A git push does not become a running app, and per-PR preview environments do not appear on their own. You either build that developer layer yourself on top of them, or use an internal developer platform that provides it. Both are valid; the question is whether building and maintaining that layer is a good use of your team's time.
What is the closest AWS equivalent to Heroku?
AWS App Runner is the closest one-to-one swap for simple apps: push a container or connect a repo and it runs, with the fewest knobs. It hits limits on networking, multi-service setups, and per-PR environments. Beyond a few simple services, teams move to ECS Fargate or EKS and often add a platform layer to get the Heroku experience back.
How do I keep Heroku Review Apps after moving to AWS?
Review Apps map to ephemeral preview environments spun up per pull request and torn down on merge. Raw AWS ships nothing equivalent, so you either build it on your CI plus infrastructure-as-code, or use an internal developer platform that provides them natively. Qovery creates one preview environment per pull request and removes it automatically, on your own AWS, GCP, Azure, Scaleway, or existing Kubernetes cluster.
How long does a Heroku to AWS migration usually take?
Most small-to-mid estates take 2 to 8 weeks: about a week to audit, a couple to containerize and stand up the target, a couple to stabilize database replication, then parallel run, rehearse, and cut over. The cutover window itself is minutes when the data is already replicated. Large databases, many services, or heavy use of Heroku-specific add-ons push the timeline longer.
The lesson I keep relearning: a Heroku exit succeeds or fails on the database and on who owns the platform after the applause dies down. Get replication right, keep a rollback open, and decide up front who runs this on day 400.
Romaric founded Qovery to make Kubernetes accessible to every engineering team. He writes about platform strategy, developer experience, and the future of cloud infrastructure.
Next step
Ship faster on infrastructure you control.
Qovery gives your team self-service deployments on your own AWS, GCP, Azure, or Scaleway account - or your existing Kubernetes cluster. Start deploying in under 10 minutes.