
Your Heroku bill crossed some threshold and somebody asked the obvious question. Then a guide told you AWS would cut it by 40 to 80 percent, and the number went into a slide. That number is almost always wrong, because it prices a dyno against a container and stops there. A Heroku to AWS migration moves real costs off your invoice and onto your engineering team. The ones that land on the team are the ones nobody models.
This article gives you the four things the ranking guides leave out. A service mapping with a column for what you now own. A cost model that includes the networking bill. The database cutover methods that actually work, given Heroku's replication limits. And the conditions under which you should stay put.
All pricing here was checked against vendor pricing pages on 3 August 2026 and every figure links to its source.
A Heroku to AWS migration moves three things: your dynos to a container runtime like ECS Fargate, your Heroku Postgres to Amazon RDS or Aurora, and your add-ons to managed AWS equivalents. The application code barely changes. What changes is ownership, because the platform work Heroku did silently now belongs to your team.
Most readers arrive thinking the choice is binary: stay on Heroku, or move to AWS. In 2026 it is a three-way choice, and the reason is buried in Heroku's own documentation rather than in any migration guide.
Four reasons come up repeatedly, and only one of them is cost. Control over networking and instance shape, because Heroku gives you dyno sizes rather than instance families. Data residency and network isolation, which on Heroku means paying for a Private Space. Postgres version and extension limits, since you cannot install an arbitrary extension or drive a major version upgrade on your own schedule. Connection ceilings, because a Standard-2 plan caps you at 400 connections whether your app needs them or not.
Here is the part missing from every guide currently ranking for this query. Heroku runs two platform generations, and Heroku's own Dev Center labels Cedar "The Legacy Platform" while recommending Fir for new and actively developed projects. If you are on Cedar, you are facing a migration either way. The question is which one.
Fir is not a free upgrade. Heroku's generations page lists these as not yet available on Fir: dyno autoscaling, Shield compliance, Heroku CI, VPC peering, VPN support, internal routing, x86 architecture support and syslog drains. Fir requires Cloud Native Buildpacks, so classic buildpacks are unsupported, and apps built on the container stack cannot migrate to Fir at all. It runs on Graviton ARM only and defaults to IPv6.
One correction worth making, because you have probably read otherwise. Heroku is not in maintenance mode. Its live pricing page sells Managed Inference and Agents with pay-as-you-go LLM and embedding models, alongside Heroku Connect for Salesforce data sync. Any guide telling you the platform is abandoned has not opened that page recently.
The assessment work that sits upstream of this decision is covered in our guide to a wider cloud migration strategy.
Use this table to build your inventory. The third column is the one that matters for planning, because it names the work that arrives on your team the day after cutover.
AWS App Runner is the closest analog to a dyno, and for a small always-on service it costs more than the dyno it replaces. That is the finding no page on this SERP will give you.
The arithmetic. App Runner pricing in us-east-1 is $0.064 per vCPU-hour and $0.007 per GB-hour. One vCPU with 2GB running continuously is $56.94 over a 730-hour month. A Heroku Standard-2X dyno is $50 for 1GB. The same shape on Fargate is $36.04, at $0.04048 per vCPU-hour and $0.004446 per GB-hour.
So the saving is real only on Fargate, at roughly $14 a month per service. Then you add the load balancer, the NAT gateway and your own time. The PaaS premium people talk about is mostly the price of not running a platform team.
The EKS cluster fee is $0.10 per cluster per hour on a supported Kubernetes version, so $73 a month before a single pod runs. That is roughly one and a half Standard-2X dynos spent on a control plane.
Every cost table on this keyword compares a dyno price to a container price and books the difference as savings. None of them price the network. Here is the same modest workload three ways: three services, a Postgres database and a Redis cache.
Read the third column, not the second. The compute saving here is $41.88 a month. Then Amazon VPC pricing puts a single NAT gateway at $0.045 per hour, which is $32.85 a month before a byte moves through it, and a normal two-availability-zone private subnet design runs two of them. That $65.70 is larger than the entire compute saving.
The rows without dollar figures are deliberate. Those prices depend on your instance class, region, storage and traffic, so any single number would be fiction. What is not in doubt is that all eight of those lines bill you and Heroku bundled them.
Then labor. The only public effort figure on this topic is One2N's account of moving a Django, Postgres and Redis application with one engineer over two months. Price two engineer-months at your own rate and put it in the model. Then add the recurring cost, because platform ownership does not end at cutover.
None of this means the migration is a bad idea. It means the honest saving usually comes from right-sizing and reserved capacity rather than from leaving Heroku, and you should know which one you are buying. Teams that want the model built against their own bill before committing use our cloud migration and modernization services for exactly that.
Eight steps, each with an exit criterion. The exit criterion is what separates a plan from a checklist.
Do steps 1 to 6 with Heroku still serving production. Only step 8 touches your users.
Start here, because this constraint invalidates the advice you have probably already read. Heroku's help center states it plainly: "We don't support logical replication from external instances for Heroku Postgres instances." That is from Heroku's own support documentation, and the feature request is still open on Heroku's public roadmap.
Two consequences. AWS DMS in change-data-capture mode cannot use Heroku Postgres as a source the normal way. Neither can a native CREATE SUBSCRIPTION on RDS pointed at Heroku. Those are the first two methods most ranking guides recommend, and 2 of the 7 pages we read recommend DMS with no caveat at all.
Here is what actually works.
Whichever method you pick, synchronize your sequences after cutover. Logical and trigger-based replication copy rows and not sequence state, so your first inserts on RDS collide with existing primary keys. The one vendor page targeting this exact query omits this step, and it produces a quiet corruption that surfaces hours later.
The downtime window is a function of the replication method available to you, not of how carefully you plan. That is worth stating because it is where teams lose control of the schedule. On one EHR platform move to Amazon Aurora, Entrans ran continuous replication with AWS DMS and achieved zero downtime on the historical cutover. That was an Oracle source, where DMS change data capture is fully supported. On Heroku Postgres you do not have that option, which is exactly why the method table above matters more than the runbook.
Also check your Postgres constraints before you promise anything: no superuser on Heroku, a restricted extension list, major version upgrades on Heroku's schedule rather than yours, and fixed storage tiers. Some of these are the reason you are migrating. Confirm the extensions you use are available on your RDS or Aurora version.
On RDS against Aurora: RDS is the like-for-like target and the simpler answer. Aurora is worth the replatform when you need read replicas with low lag or storage that grows without a maintenance event. Aurora Serverless v2 suits spiky or non-production workloads where paying for a fixed instance around the clock makes no sense. For a first migration, land on RDS and move later if the numbers justify it. The mechanics of a Postgres platform change are covered in more depth in our Oracle to Postgres migration guide.
On Heroku, platform controls sat with Heroku. On AWS they sit with you under the shared responsibility model, and that handover is the part four ranking pages assert and none operationalize.
The current fact that changes the decision for regulated teams: Shield is a Cedar-only product, and Heroku describes Fir's SOC certifications as coming rather than held. If compliance coverage is why you are reviewing your platform, Fir is not yet the answer and Cedar is the legacy generation. That narrows the choice considerably.
After cutover you own the evidence. That means encryption configuration at rest and in transit, IAM access reviews with dates, audit logging and its retention. It also means backup restore tests you have actually run, patch records for your base images, and change records for network rules. Name an owner for each before the migration rather than during the first audit. Note that architecture alone does not make an organization compliant with HIPAA, SOC 2, PCI DSS or GDPR. It determines which controls you can evidence, and the rest is process.
Platform ownership arrives on day one after cutover, and no page on this SERP converts it into a role. Here is the work. Base image patching, certificate rotation, IAM access reviews and cost anomaly triage. VPC and security group changes, RDS maintenance windows, and backup restore tests. Plus being the person paged at 3am when a task fails its health check.
That is a fraction of an engineer permanently, not a project. Budget it as a named responsibility. If nobody's job description changes after the migration, the migration is not finished, it is just deployed.
There is a real counterweight, and it is under-used in these discussions. Checkly's honest finding after moving was that AWS let junior engineers do work that had needed senior engineers on Heroku, because the platform stopped being a specialist skill. The AWS labor market is also far deeper than the Heroku one. You are trading a smaller amount of specialist knowledge for a larger amount of common knowledge, which is usually the better trade for a growing team. Teams that would rather not carry the on-call rotation in-house hand it to a partner, which is what our DevOps and platform engineering support covers.
Find the row whose best-fit condition matches your actual constraint, then read the column for what you give up. Most teams discover their constraint is narrower than the migration they were planning.
Three conditions where this migration is the wrong call, and what to do instead.
Your Heroku bill is too small for the arithmetic to work. Below roughly $1,000 a month, the two engineer-months plus the AWS baseline for NAT gateways, load balancers and CloudWatch will exceed anything you save. A $65.70 networking floor eats a large share of a small saving before you start. Do this instead: right-size your dynos, drop over-provisioned Postgres plans a tier, and re-measure. In our delivery work, most of the saving on a cloud cost review comes from right-sizing rather than from changing platform, and you can do that this week without a migration.
The platform is not your performance problem. One2N's starting point was p99 latency above 8 seconds at under 600 requests per minute. That is not a dyno limit, that is a query plan or a missing index, and AWS will happily reproduce it on faster hardware. Do this instead: profile your slowest endpoints, fix the queries, then re-measure. If latency is still bad at reasonable load, the platform argument becomes real.
Fir or a Private Space already answers your requirement. If the trigger was network isolation or data residency rather than cost or control, check Heroku's Private Spaces and Fir first. A weeks-long generation upgrade beats a months-long cloud migration when both end in the same place.
One thing we would advise against, and it costs us work to say: do not re-architect to microservices during the migration. Teams reason that since they are touching everything anyway, they may as well split the monolith. Two risky projects at once means you cannot tell which one broke production, and a four-week cutover becomes a two-quarter program. Move it as it is, stabilize, then decompose on purpose.
Most Heroku to AWS projects go wrong on two things: the database cutover method and the costs nobody modeled. Entrans runs a two-week migration assessment that fixes both. We inventory your Heroku estate and test which replication method your Postgres plan actually supports. You get back a landed-cost model with the networking and observability lines included, plus a cutover and rollback plan. One recent client migration cut infrastructure cost 50 percent, mostly through right-sizing rather than the move itself. Book a 20-minute consult with Entrans's cloud and data engineering architects.
AWS App Runner is the closest equivalent to a Heroku dyno, because it runs an always-on container with a managed HTTPS endpoint and built-in autoscaling. ECS Fargate is the more common target and costs less, but you take on the VPC, load balancer and task definitions yourself. Elastic Beanstalk sits between them.
Sometimes, and the saving is smaller than most guides claim. AWS App Runner at 1 vCPU and 2GB costs $56.94 a month, more than the $50 Heroku Standard-2X dyno it replaces. The saving appears on ECS Fargate at $36.04, and only after you absorb NAT gateway, egress, CloudWatch and engineering costs.
Not with AWS DMS change data capture or a native RDS subscription, because Heroku states it does not support logical replication from external instances. Teams reach near-zero downtime two other ways: a WAL restore into an intermediate Postgres instance followed by logical replication to RDS, or trigger-based replication using Bucardo.
Yes. Heroku has always run on AWS infrastructure, and its Fir generation is explicitly built on AWS EKS, Graviton and Global Accelerator according to Heroku's own documentation. So this migration does not put you on AWS for the first time. It moves the platform layer from Heroku's team to yours.
Plan two to three months for a production estate with one database, based on the two public accounts available. Checkly planned four weeks for a 300GB Postgres migration and took five. One2N moved a Django, Postgres and Redis application with one engineer over two months. Database rehearsal consumes most of that time.
Consider first if your driver is Heroku's older platform rather than cost or control, since it is a much smaller project. Read Heroku's generations documentation before committing: Fir currently has no dyno autoscaling, no Shield compliance, no Heroku CI and no VPC peering, and it requires Cloud Native Buildpacks on Graviton.
Skip the migration when your Heroku bill is small enough that engineering time plus the AWS networking and observability baseline exceeds the saving. Stay put when your latency problem is a query plan rather than a platform, because AWS will reproduce it. And check Fir Private Spaces first if the isolation or residency requirement is what triggered your review.


