Heroku's Free Tier Is Gone — A Migration Checklist That Doesn't Break Production
Yesterday, November 28, Heroku switched off its free dynos, free Postgres and free Redis — the end of a platform that, for over a decade, was the default answer to "where do I put my side project?" The shutdown was announced back in August, so nobody can claim surprise, but announcements and action are different things: a lot of apps are being migrated this week in a hurry, and a hurried migration is exactly how a working app becomes a down one.
If you're mid-move — or staring at a sleeping dyno that will never wake again — this post covers where projects are actually going, and more importantly, how to cut over without breaking things: monitoring both sides, getting DNS right, and verifying the app works on the new host rather than merely responds.
What actually shut down
To be precise about the blast radius: free Heroku dynos stopped running, free hobby-dev Postgres databases and free Redis instances are being deleted, and inactive accounts are targeted for removal. Heroku has been emailing affected users for months, and it introduced low-cost paid plans — Eco dynos and Mini Postgres — for people who'd rather pay a little than move at all.
That's a legitimate option, and the laziest safe one: flip the app to Eco, keep everything else identical, migrate later on your own schedule. But if the project earns nothing, plenty of people are choosing to relocate instead — and the ecosystem has genuine alternatives now.
Where the hobby projects are going
Four destinations come up over and over in this migration wave:
- Render — the most Heroku-like experience: connect a repo, get builds and deploys, managed Postgres available. Its free web services spin down after inactivity, and the first request afterwards waits out a cold start that can take tens of seconds. Fine for a demo; worth knowing before you point real users at it.
- Fly.io — runs your app as small VMs close to users, with a free allowance that covers a couple of tiny instances. More knobs than Heroku (a
fly.toml, regions, volumes), which is either a feature or a chore depending on your appetite. Apps on the free allowance run continuously rather than sleeping, which matters for anything latency-sensitive. - Railway — the closest thing to Heroku's "it just deploys" feel, with a usage-based starter allowance rather than an unlimited free tier. Reportedly a large share of this week's refugees are landing here and on Render; expect the occasional growing pain from any platform absorbing a wave like this.
- A cheap VPS — the old answer becoming new again. A few dollars a month buys a small server that never sleeps and has no platform limits, in exchange for you becoming the platform team: OS updates, a reverse proxy, a process supervisor, and Postgres backups are now your job. Great for learning; honest about the trade.
The common thread: every free tier that replaced Heroku's has sharper edges than Heroku's did. Spin-downs, usage caps, resource limits. Whatever you pick, read the limits page before migrating, not after the first mysterious outage.
Monitor both sides before you touch anything
The single highest-leverage move in any migration costs five minutes: put uptime monitoring on the old app and the new one before the cutover, and keep both until well after.
- The old app, because you need to know exactly when it stops serving — and whether stragglers with cached DNS are still hitting it days later.
- The new app on its platform URL (
yourapp.onrender.com,yourapp.fly.dev) so you're validating the deployment itself, separate from DNS. - The real domain, so you see what users see through the entire transition.
During cutover, the monitors tell the story in real time: platform URL healthy, old host still serving, then traffic shifting as DNS propagates. Without them, your migration status is a vibe. With them, it's a timeline.
DNS: turn the TTL down before you move
DNS is where cutovers go to die slowly. The TTL on your records tells resolvers how long to cache them — and if it's sitting at 24 hours, some fraction of your users will keep hitting the dead Heroku app for up to a day after you "finished."
The sequence:
; days BEFORE cutover — lower the TTL so caches expire fast
app.example.com. 300 IN CNAME yourapp.herokuapp.com.
; cutover — repoint at the new platform; changes now propagate in ~5 minutes
app.example.com. 300 IN CNAME yourapp.onrender.com.
; a day or two AFTER, once stable — restore a sane TTL
app.example.com. 3600 IN CNAME yourapp.onrender.com.
Lower the TTL at least one old TTL-length before the move (a 24-hour TTL needs lowering 24+ hours ahead — resolvers must expire the old value first). And remember the pieces that aren't the web app: apex/www records, MX, TXT records for email, and any subdomains quietly CNAMEd to Heroku.
Databases and the app that "works"
Move the data with a proper dump-and-restore (pg_dump from Heroku, restore to the new provider), put the old app in maintenance mode during the final sync so you don't strand writes, and keep the Heroku dump — free databases are being deleted, not paused, so it may soon be the only copy of your history.
Then verify the app actually works — not just that it returns 200s:
- A 200 from a health check proves the process is up. It does not prove the database connected, migrations ran, environment variables came across, or the session store points at the new Redis rather than a dead free one.
- Use keyword checks. Assert the response body contains something that only renders when the app truly works — real data from the database, a logged-in dashboard string — and that it doesn't contain
Application erroror a stack trace. Half-broken apps serve 200s all day. - Exercise the paths that touch every dependency. Sign in, create a record, trigger the email. Config drift loves to hide in exactly the features a homepage check never touches — and cross-check that scheduled jobs came along too, since Heroku Scheduler tasks don't migrate themselves.
Migrate with your eyes open
Heroku's free tier had a good run. Whatever replaces it for your project, the migration itself doesn't have to be a gamble: monitors on both sides, TTL lowered in advance, data verified, and checks that assert on content rather than status codes.
CompleteStatus covers the whole cutover from one dashboard — uptime checks with keyword assertions on the old host, the new platform URL and your real domain, plus DNS monitoring that catches records still pointing at the ghost of a free dyno. Alerts go wherever your team lives — Slack, Discord, Telegram or webhooks — so the first sign of a botched cutover is a ping, not a user complaint. Create a free account and put monitors on both sides before you touch DNS. Five minutes of setup, and you'll be the one migration this week that saw everything.