DEV Community

Cover image for I Cut My Rails Hosting Costs by 70%: Migrating from Heroku to Railway
Paul Works
Paul Works

Posted on

I Cut My Rails Hosting Costs by 70%: Migrating from Heroku to Railway

I Cut My Rails Hosting Costs by 70%: Migrating from Heroku to Railway

For a while, I was hosting a small Rails API on Heroku with JawsDB as the MySQL database.

It worked perfectly. Heroku’s developer experience is still one of the best out there.

But for a small personal project, I realized I was paying more than necessary.

So I migrated the app and database to Railway and reduced my hosting costs from roughly ~$20/month to ~$6/month — about a 70% reduction.

The best part: the migration took less than 30 minutes.

Here’s exactly how I did it.


TL;DR

I migrated a Rails API from Heroku + JawsDB to Railway.

Results:

  • Hosting cost reduced from ~$20/month → ~$6/month
  • Migration took ~20–30 minutes
  • No downtime
  • Database migrated using one streaming command

My Original Setup

My stack looked like this:

Rails API
   │
Heroku Dyno
   │
JawsDB (MySQL)
Enter fullscreen mode Exit fullscreen mode

Approximate monthly cost:

Service Provider Cost
App hosting Heroku ~$7–10
MySQL JawsDB ~$10–12
Total ~$20/month

Again, not huge — but for side projects, I prefer keeping infrastructure simple and inexpensive.


The New Setup

After migrating:

Rails API
   │
Railway App
   │
Railway MySQL
Enter fullscreen mode Exit fullscreen mode

New cost breakdown:

Service Provider Cost
App hosting Railway ~$3–4
MySQL Railway ~$2
Total ~$6/month

That’s roughly a 70% cost reduction.


Migration Strategy

The migration consisted of four steps:

  1. Link the Railway project
  2. Export the database from JawsDB
  3. Import the data into Railway MySQL
  4. Update the Rails configuration

No downtime was required.


Step 1: Link Your Railway Project

First install and authenticate with the Railway CLI.

Then run:

railway link
Enter fullscreen mode Exit fullscreen mode

What this does:

  • Connects your local repo to your Railway project
  • Allows the CLI to run commands against that project
  • Creates a .railway folder locally

This step only needs to be done once per repository.


Step 2: Dump Data from JawsDB and Import into Railway

Instead of creating a dump file and importing it later, you can stream the database directly.

Here’s the command I used:

mysqldump \
-h [jawsdb-host] \
-u [jawsdb-user] \
-p[jawsdb-password] \
--no-tablespaces \
--set-gtid-purged=OFF \
--single-transaction \
[jawsdb-database] \
| railway run -s MySQL mysql \
-h $MYSQLHOST \
-u $MYSQLUSER \
-p$MYSQLPASSWORD \
$MYSQLDATABASE
Enter fullscreen mode Exit fullscreen mode

This command:

  1. Exports the database from JawsDB
  2. Pipes the output directly into Railway MySQL

Why These Flags Matter

--no-tablespaces

JawsDB runs on AWS RDS, which restricts certain privileges required for dumping tablespaces.

This flag avoids that issue.

--set-gtid-purged=OFF

Prevents replication metadata from causing conflicts during import.

--single-transaction

Creates a consistent snapshot of the database while exporting.

This works well for InnoDB tables, which most Rails apps use.


Why Streaming the Database Is Powerful

The pipe (|) streams the SQL output directly into Railway.

JawsDB → mysqldump → pipe → Railway MySQL
Enter fullscreen mode Exit fullscreen mode

Benefits:

  • No intermediate dump files
  • Faster migration
  • Lower disk usage
  • Works well for large databases

Step 3: Verify the Migration

After the import, verify the migration with:

railway run -s MySQL mysql \
-h $MYSQLHOST \
-u $MYSQLUSER \
-p$MYSQLPASSWORD \
$MYSQLDATABASE \
-e "SHOW TABLES;"
Enter fullscreen mode Exit fullscreen mode

If the migration worked correctly, you should see your tables:

users
transactions
posts
comments
Enter fullscreen mode Exit fullscreen mode

Step 4: Update Rails Configuration

Previously, my Rails app used the JawsDB DATABASE_URL.

Railway automatically provides environment variables:

MYSQLHOST
MYSQLPORT
MYSQLUSER
MYSQLPASSWORD
MYSQLDATABASE
MYSQL_URL
Enter fullscreen mode Exit fullscreen mode

The simplest Rails configuration is:

production:
  adapter: mysql2
  url: <%= ENV['MYSQL_URL'] %>
Enter fullscreen mode Exit fullscreen mode

After pushing the code, Railway automatically redeployed the application.


Heroku vs Railway (Quick Comparison)

Here’s a quick comparison based on my experience migrating a small Rails API.

Feature Heroku + JawsDB Railway
Hosting model App dynos + add-ons App + services in one platform
Database JawsDB MySQL add-on Native managed MySQL
Cost (small project) ~$20/month ~$6/month
Deployment Git push Git push / GitHub integration
Environment variables Supported Supported
CLI tools Heroku CLI Railway CLI
Database migration Manual dump/import Easy via railway run
Infrastructure management Managed Managed
Static outbound IP Not guaranteed Not guaranteed
Best suited for Mature production apps Side projects & small apps

Final Thoughts

Heroku still offers one of the best developer experiences.

But for small projects or side tools, simplifying infrastructure and reducing costs can make sense.

For my Rails API, moving to Railway:

  • simplified my stack
  • reduced hosting costs by ~70%
  • required minimal migration effort

If you're running a small Rails project with MySQL on Heroku, exploring Railway might be worth considering.


Question for Other Developers

If you're hosting side projects:

  • Are you still using Heroku?
  • Or have you moved to platforms like Railway, Fly.io, or Render?

I'd love to hear what your stack looks like.

Top comments (0)