Home | 2022-09-07 | © James Hudson

Migrating your Django app off Heroku, and onto a fresh new (free) Platform-as-a-Service

Who is this for?

Developers who are sad that Heroku no longer offers free tiers, and/or service owners who wince at their monthly bills.

This is a review of the process of migrating Heroku-hosted services onto other "Platform as a Service" (PaaS) providers, and my initial experience with that process.

Django is my preferred platform for most web projects, so that is the specific platform I will discuss.

This article goes into some technical details for developers who are considering migrating an existing Django app from Heroku to another platform.

Why am I moving off Heroku?

Recently, Heroku, the original "Platform as a Service" company, made an announcement that it was ending its free tier of web service hosting. This killed off my main reason for staying with Heroku, and it seems I am not alone. There has been a flood of blog posts in my search results, such as: "Getting off Heroku", "Heroku alternatives", and "Migrating from Heroku to ...".

Heroku has been a fantastic tool for my freelance business over the last decade, but this was before the Docker revolution. The platform has not really innovated during that time, considering all the deployment options we now have. Heroku's choice to remove their free tier was a deal-breaker.

I am a happily-paying Heroku customer, and I have customers whom I have convinced to use Heroku, but it will no longer be my go-to choice for new projects. Heroku is relatively expensive, and I don’t want to pay for every single instance of staging servers, experimental projects, small apps, or non-profit services that I might end up doing in the future.

Reasons to stay on Heroku

Heroku has been around for ages. There is loads of documentation on every possible configuration. They seem to have included every obscure library you would ever need in their Buildpacks.

There is a huge list of third-party plugins for Heroku. One alternative which I tried did not even have cron, but required a janky extra VM instance which called a cron library.

The alternatives I tried were still under development, with plenty of rough edges and missing functionality which stopped them from being a seamless replacement for Heroku.

Why not AWS or own “bare metal” server?

If you are a small team mostly developing Minimal Viable Products, or trying out small projects or experiments, then server maintenance does not add value to your business. Learning the ins and outs of AWS and container management is a job in itself, and can have hidden cost traps. I have found it liberating to outsource the platform work, so I only think about infrastructure at the abstraction level of git and above.

The contenders

I decided to put some small, unimportant services on each platform as a test. This is my experience of doing the minimal setup possible to migrate these couple of services from Heroku. I did not dig deeply into any of the PaaSs, so please don’t consider this an in-depth review.

On Railway.app I installed a service that includes PDF export (using the Weasyprint library) and additional binary library packages. This makes it more complicated to deploy than the average Django CRUD/CMS.

On Fly.io I installed a simple REST API and CMS for an app.

I have not had enough time to see how they perform over time with these real services, or what the long-term costs would look like.

My very non-scientific ratings

Railway.app

https://railway.app

Also note:

Fly.io

https://fly.io

Also note:

Nope: the alternatives that didn't make the cut

OpenShift

I did try openshift years ago, but they made their lowest tier more expensive than Heroku.

Heroku

No free tier as of November 2022.

Render

Free tier database wipes every 3 months, making it unusable for any real project.

Code snippets

These might help you with your own migration:

Export old database from Heroku

Run this code from your local machine to export your old Heroku database

heroku login
heroku run 'pg_dump $DATABASE_URL' > backup.sql --app <your app name>

Note that $DATABASE_URL will be filled by the Heroku environment, so type it as is here.

railway.app

Import database dump into railway.app:

(Copy/paste the from Railway’s PostgreSQL/Connect dashboard and add the -f backup.sql at end) PGPASSWORD= psql -h -U -p -d -f heroku_backup.sql


This might be a bit of an unneccesary security hole, but it sure is convenient.

Fly.io

Deploy

Had some issues deploying - needed to use this line for deploy to use my local Docker daemon:

flyctl deploy --verbose --local-only

Import database

I needed to open a local proxy to the database:

flyctl proxy 5400:5432 -a name—of-app-db

And then do my migration manually by

flyctl ssh console -a <app name> python manage.py migrate

Then manually copy/pasting the important data from the SQL dump into a Postgres shell.

flyctl postgres connect -a < app name >-db

Then something like:

postgres=# COPY < table > (id, schoolid, classtypeid) FROM stdin; Enter data to be copied followed by a newline. End with a backslash and a period on a line by itself, or an EOF signal.

24 24 5

29 63 5

32 30 5

35 72 5

36 61 5

37 77 5

Overall winner`: Railway.app

https://railway.app

The effortless setup, true "free" tier, attractive pricing, good support, and beautiful dashboard, make this a clear winner for my small projects. However, it's still a new service, so I'll see how it runs for a while on my small projects before I host any commercial projects there.

Summary

Both Railway and Fly gave me a few genuine moments of thinking: "wow, that is really cool", as I was setting them up. Perhaps they still have some rough edges, but I'm excited by their potential. Railway feels closer to the ideal of "just show it some code, and the service is running".

Perhaps Render is still worth it despite the lack of a proper free tier. But I'm not paying for my staging servers, experiments, or apps with miniscule user bases, when there are excellent free options out there.

I'll continue paying Heroku for my existing commercial services, but it will no longer be my go-to PaaS for new projects. As my Heroku projects scale, I'll migrate them too, for the added features and lower costs elsewhere.

In closing, I would say that us small developers are spoiled for choice; we just have so many interesting options.

James Hudson

If you have any thoughts on this, please email me. Or at least "like" or "share" this post if you think others would appreciate it.


OTHER POSTS:

It's Monday morning, but I don't have to go to work. Ever again.
Become a Part-Time Superhuman: Work a 4-Hour-Day
Adequate is better than more: your life as the perfect kitchen
This is the Sales Manual you should have been given at graduation
I'll build your app to help you become independent. For free.
Why there is no Facebook killer: the death of the P2P dream
How to become a freelancer in Berlin: the tricks and the traps
How to write a proposal they can't refuse
Programming basics for everyone: how to try coding right now, and why you need to.
Poledancing versus programming: break away from your business and run it remotely.
The Freelancer's Code of Ethics: doing good, standing up for yourself, and not burning down the building.
The Tragic Flaws of Terrible Projects
Migrating your Django app off Heroku, and onto a fresh new (free) Platform-as-a-Service

Disclaimer

Needless to say, this blog isn't financial or legal advice, an excuse for getting fired, or promising that any of these ideas will work for you. The companies or people I mention may not agree with my opinions here. Don't do anything reckless, damaging or hurtful to anyone! In the future you might need your bridges unburnt. Images used under fair use, and are copyright their respective owners. © 2014-2022 James Hudson