Skip to main content

Render Taught an AI Agent to Migrate Your Heroku App: What It Gets Right, What Still Needs You, and the Bill at the End

9 min readDora NodaDora Noda
Share
On this page

On February 6, 2026, Salesforce said the quiet part out loud: Heroku is moving to a "sustaining engineering" model. No new features. No new Enterprise contracts. Engineering investment redirected toward enterprise AI. Your dynos keep running, your bill keeps coming — but the platform underneath them has officially stopped moving forward.

That announcement turned every Heroku app into a migration backlog item with no due date but no alternative either. And Render noticed. Its 2026 migrate-from-Heroku push pairs the usual docs with something new: an open-source agent skill, render-migrate-from-heroku in the render-oss/skills repo, that lets an AI agent connected over MCP do the migration itself — read your Procfile, map your dynos, copy your config vars, move your Postgres — in minutes, with no manual YAML editing.

I read the skill end to end, including its reference docs, to answer the only question that matters: what does the agent actually get right, what still needs a human, and what does the bill look like on the other side? Here is the concrete version.

The bill first: two real stacks, before and after

Every migration post buries the numbers. Here they are up front, computed from both vendors' current pricing pages — with the honest caveat the skill itself carries: confirm plan charges at Render pricing before you budget, because tiers move.

Stack A — the hobby app. One Eco dyno ($5/mo for 1,000 dyno hours) plus an Essential-0 Postgres ($5/mo, 1 GB). Heroku total: $10/mo. On Render that maps to a Starter web service ($7/mo, 512 MB — the same RAM as the Eco dyno) plus a Basic-256mb Postgres (~$6/mo). Render total: ~$13/mo.

Read that twice: at the hobby tier, Render is slightly more expensive at base. If anyone tells you migration is always about saving money, show them this table. For Stack A, the reason to move isn't price — it's that the $10/mo platform is frozen and the $13/mo one isn't.

Stack B — the small production app. Two Standard-1X dynos, web plus worker ($25 each), a Standard-0 Postgres ($50/mo), and a Redis Mini add-on ($3–15/mo depending on plan). Heroku total: ~$103–115/mo. On Render: two Starter services ($7 each), a Basic-tier Postgres ($6/mo at the small end; Standard-0's 4 GB RAM maps to Render's Pro Postgres tier, so confirm the current price), and a Key Value Starter instance ($10/mo). Render total: roughly $30/mo and up — about a third of the Heroku number.

Why does the delta flip so hard between stacks? Because Heroku charges $25 for 512 MB of dyno that Render prices at $7. The entire Heroku-to-Render arbitrage lives in that one ratio. The moment your app outgrows Eco, every additional 512 MB dyno-shaped unit costs 3–4x more on Heroku than on Render — and that ratio compounds with each dyno you add.

Where the answer varies — the sensitivity check. Base prices are not the whole bill on either side, and three meters move the Render number after migration:

  • Bandwidth overages at $0.15/GB. A quiet internal tool never notices; an image-heavy public app can add tens of dollars. Heroku's dyno pricing never taught you to watch egress — Render's meter will.
  • Build minutes at roughly $5 per 1,000. A team deploying twenty times a day pays a different total than one deploying weekly.
  • Preview environments and autoscaling live behind the paid workspace tier (~$25/mo), not the free Hobby workspace. If your Heroku pipeline leans on review apps, that line belongs in the budget from day one.

The honest summary: Stack A migrates for the roadmap, Stack B migrates for the money, and both need the metered lines added before anyone quotes a total.

How the skill actually works, in six steps

The skill (v1.5.0, MIT-licensed, authored by Render) is refreshingly mechanical. It doesn't ask the agent to be clever — it gives it a checklist with two MCP servers attached:

  1. Inventory from local files first. The agent reads your Procfile (process types and start commands), app.json (declared add-ons, buildpacks), dependency files (package.json, requirements.txt, Gemfile, go.mod), and runtime.txt — never assuming a runtime version, only carrying over pinned ones as env vars like PYTHON_VERSION.
  2. Optional live enrichment over MCP. If the Heroku MCP server is connected, the agent pulls real config vars, add-on plans, and dyno sizes. If not, it asks you to paste the output of heroku ps:type, heroku addons, and heroku pg:info. The migration degrades gracefully instead of blocking.
  3. Create, two ways. Either generate a render.yaml Blueprint (the declarative path — full example included for a web dyno plus worker plus Scheduler plus Postgres plus Key Value) or create services directly through the Render MCP server. The skill recommends MCP for direct creation and automated verification, but the Blueprint path needs nothing but the CLI and dashboard.
  4. Move config vars in bulk via the Render MCP's environment-variable update — merged, not clobbered.
  5. Move the data by size tier. Under 2 GB goes through render psql, no connection string needed on the Render side. Between 2 and 50 GB goes through pg_dump -Fc plus pg_restore, with connection strings gathered from both sides. (Notably, the skill is explicit that neither MCP server can run the dump itself — the agent generates the commands, you or your shell run them. Agents orchestrate; pipes still move bytes.)
  6. Verify automatically — pre-migration checks confirm the Render Postgres and Key Value instances exist, and post-migration steps confirm the app actually answers before DNS cutover.

Total human YAML editing required: zero, if you take the MCP path. That part of the marketing claim checks out.

What the agent genuinely gets right

Three things in the skill's reference docs surprised me with their care:

RAM-matched dyno mapping, not name-matched. The service-mapping table maps by megabytes, so Eco, Basic, and Standard-1X — all 512 MB despite their $5/$7/$25 prices — all land on Render's starter. Standard-2X (1 GB) goes to standard, Performance-M (2.5 GB) to pro, all the way up to Performance-2XL (126 GB) mapping to a 128 GB custom plan. Matching on RAM instead of plan names is exactly the mistake a human doing this by hand makes most often, and the agent simply doesn't.

Postgres tiering that respects HA. Heroku's Standard and Premium tiers share numbering but differ in that Premium includes high availability. The skill maps both to the same Render plan and tells the agent to enable HA explicitly to match Premium — flagging that the standby instance is separately billed. A naive migration would either silently drop your failover or silently double your database bill; this one does neither.

A preflight checklist that reads like an incident review. Source database size, CLI availability, connection strings from both sides, confirmation before creating any billable resource — the skill presents findings and waits for approval before spending your money. Whoever wrote it has watched an agent provision infrastructure unsupervised before.

What still needs a human

And now the other list — the one that determines whether "migrate me" is an afternoon or a quarter:

Add-on parity ends at Postgres and Key Value. The skill migrates exactly two data services. Everything else — SendGrid, Papertrail, Scheduler-era cron specifics, any bespoke add-on — stays on Heroku with its env vars copied over, which means your "migrated" app still has a Heroku invoice and a Heroku dependency. Each remaining add-on is its own mini-migration the agent doesn't cover.

Review-app pipelines don't translate. Heroku Pipelines with per-PR review apps are release process, not just infrastructure, and there is no line in the skill for them. Render's preview environments are the destination, but they need the paid workspace tier and a re-thinking of promotion flow — a human design decision, not a mapping table.

Cron has a ceiling. Render cron jobs top out at the pro plus plan (4 CPU / 8 GB). A Heroku scheduler process at Performance-L or above has no Render cron equivalent — the skill says so plainly and suggests splitting the job or moving it to a worker. That's correct advice, and it's also a small re-architecture wearing a migration costume.

Big databases and edge runtimes are out of scope. Over 50 GB, the size-tiered transfer playbook ends and you're writing your own cutover plan. Apps on Heroku's newer Fir generation (where Docker deploys aren't supported) carry their own constraints. And the bill-shock trio from the sensitivity check — bandwidth, build minutes, workspace tier — is precisely the kind of thing nobody notices until the second invoice.

None of this invalidates the skill. It bounds it: the agent reliably moves the app-shaped middle — web, worker, config, database — and hands you a short, specific list of everything else. "Minutes" is true for the middle. Budget humans for the edges.

The lesson for self-hosted fleets: what your MCP server must expose

Here is why this matters beyond Render. The skill is a proof that "migrate me off Heroku" can be a prompt instead of a project — but only because two MCP servers expose the right verbs. Strip it down and the pattern is a five-capability checklist any platform needs before an agent can operate it:

  1. Inventory — list apps, dyno sizes, add-ons, config shapes (Render's list_services, Heroku's list_apps).
  2. Plan mapping — a machine-readable translation table between the old world's SKUs and yours, matched on resources (RAM, disk), not names.
  3. Secret migration — bulk environment-variable transfer that merges instead of clobbering, with explicit human confirmation before anything billable happens.
  4. Data transfer — size-tiered playbooks with honest boundaries about what the agent orchestrates versus what still needs a shell.
  5. Verification — post-migration health checks the agent can run itself before cutover, not a "deploy and pray" step.

And one meta-requirement over all five: scope. The agent never gets raw kubectl or a blank-check API key — it gets a tool surface bounded by RBAC, spend budgets, and an audit log of every action. "The agent can migrate my app" and "the agent can do anything to my fleet" must never be the same permission.

That is the actual bar. Render cleared it with a versioned skill file, two MCP servers, and a mapping table. Any self-hosted PaaS that wants agents as first-class operators — migrations today, deploys and incident response tomorrow — needs the same five verbs behind the same kind of scoped surface. The migration skill isn't just a Heroku-exit tool. It's the reference implementation for agent-operated infrastructure, and it's MIT-licensed. Go read it.

Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own. Star the repo on GitHub or deploy your first app today.

Related articles

Give your agents a chain backend

Autonomous agents hit RPC endpoints very differently than people do. See what bex router handles on their behalf.

Read the agents guide