<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Paul Works</title>
    <description>The latest articles on DEV Community by Paul Works (@paulworks).</description>
    <link>https://dev.to/paulworks</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3812869%2F6d52115f-134a-40c7-a90d-5e3cd9f64d60.png</url>
      <title>DEV Community: Paul Works</title>
      <link>https://dev.to/paulworks</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/paulworks"/>
    <language>en</language>
    <item>
      <title>I Cut My Rails Hosting Costs by 70%: Migrating from Heroku to Railway</title>
      <dc:creator>Paul Works</dc:creator>
      <pubDate>Sun, 08 Mar 2026 14:59:09 +0000</pubDate>
      <link>https://dev.to/paulworks/i-cut-my-rails-hosting-costs-by-70-migrating-from-heroku-to-railway-22op</link>
      <guid>https://dev.to/paulworks/i-cut-my-rails-hosting-costs-by-70-migrating-from-heroku-to-railway-22op</guid>
      <description>&lt;h1&gt;
  
  
  I Cut My Rails Hosting Costs by 70%: Migrating from &lt;a href="https://www.heroku.com/" rel="noopener noreferrer"&gt;Heroku&lt;/a&gt; to &lt;a href="https://railway.com?referralCode=kZLahu" rel="noopener noreferrer"&gt;Railway&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;For a while, I was hosting a small Rails API on Heroku with JawsDB as the MySQL database.&lt;/p&gt;

&lt;p&gt;It worked perfectly. Heroku’s developer experience is still one of the best out there.&lt;/p&gt;

&lt;p&gt;But for a small personal project, I realized I was paying more than necessary.&lt;/p&gt;

&lt;p&gt;So I migrated the app and database to &lt;a href="https://railway.com?referralCode=kZLahu" rel="noopener noreferrer"&gt;Railway&lt;/a&gt; and reduced my hosting costs from roughly &lt;strong&gt;~$20/month to ~$6/month&lt;/strong&gt; — about a &lt;strong&gt;70% reduction&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The best part: the migration took less than &lt;strong&gt;30 minutes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here’s exactly how I did it.&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;I migrated a Rails API from &lt;strong&gt;Heroku + JawsDB&lt;/strong&gt; to &lt;strong&gt;Railway&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Results:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hosting cost reduced from &lt;strong&gt;~$20/month → ~$6/month&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Migration took &lt;strong&gt;~20–30 minutes&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;No downtime&lt;/li&gt;
&lt;li&gt;Database migrated using &lt;strong&gt;one streaming command&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  My Original Setup
&lt;/h2&gt;

&lt;p&gt;My stack looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Rails API
   │
Heroku Dyno
   │
JawsDB (MySQL)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Approximate monthly cost:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;App hosting&lt;/td&gt;
&lt;td&gt;Heroku&lt;/td&gt;
&lt;td&gt;~$7–10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MySQL&lt;/td&gt;
&lt;td&gt;JawsDB&lt;/td&gt;
&lt;td&gt;~$10–12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~$20/month&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Again, not huge — but for side projects, I prefer keeping infrastructure simple and inexpensive.&lt;/p&gt;




&lt;h2&gt;
  
  
  The New Setup
&lt;/h2&gt;

&lt;p&gt;After migrating:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Rails API
   │
Railway App
   │
Railway MySQL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;New cost breakdown:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;App hosting&lt;/td&gt;
&lt;td&gt;Railway&lt;/td&gt;
&lt;td&gt;~$3–4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MySQL&lt;/td&gt;
&lt;td&gt;Railway&lt;/td&gt;
&lt;td&gt;~$2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~$6/month&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That’s roughly a &lt;strong&gt;70% cost reduction&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Migration Strategy
&lt;/h2&gt;

&lt;p&gt;The migration consisted of four steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Link the &lt;a href="https://railway.com?referralCode=kZLahu" rel="noopener noreferrer"&gt;Railway&lt;/a&gt; project
&lt;/li&gt;
&lt;li&gt;Export the database from JawsDB
&lt;/li&gt;
&lt;li&gt;Import the data into &lt;a href="https://railway.com?referralCode=kZLahu" rel="noopener noreferrer"&gt;Railway&lt;/a&gt; MySQL
&lt;/li&gt;
&lt;li&gt;Update the Rails configuration
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No downtime was required.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Link Your Railway Project
&lt;/h2&gt;

&lt;p&gt;First install and authenticate with the &lt;a href="https://railway.com?referralCode=kZLahu" rel="noopener noreferrer"&gt;Railway&lt;/a&gt; CLI.&lt;/p&gt;

&lt;p&gt;Then run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;railway &lt;span class="nb"&gt;link&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What this does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Connects your local repo to your &lt;a href="https://railway.com?referralCode=kZLahu" rel="noopener noreferrer"&gt;Railway&lt;/a&gt; project&lt;/li&gt;
&lt;li&gt;Allows the CLI to run commands against that project&lt;/li&gt;
&lt;li&gt;Creates a &lt;code&gt;.railway&lt;/code&gt; folder locally&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This step only needs to be done &lt;strong&gt;once per repository&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Dump Data from JawsDB and Import into Railway
&lt;/h2&gt;

&lt;p&gt;Instead of creating a dump file and importing it later, you can &lt;strong&gt;stream the database directly&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here’s the command I used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mysqldump &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-h&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;jawsdb-host] &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;jawsdb-user] &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-p&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;jawsdb-password] &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--no-tablespaces&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--set-gtid-purged&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;OFF &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--single-transaction&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;jawsdb-database] &lt;span class="se"&gt;\&lt;/span&gt;
| railway run &lt;span class="nt"&gt;-s&lt;/span&gt; MySQL mysql &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-h&lt;/span&gt; &lt;span class="nv"&gt;$MYSQLHOST&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="nv"&gt;$MYSQLUSER&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-p&lt;/span&gt;&lt;span class="nv"&gt;$MYSQLPASSWORD&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nv"&gt;$MYSQLDATABASE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Exports the database from JawsDB
&lt;/li&gt;
&lt;li&gt;Pipes the output directly into &lt;a href="https://railway.com?referralCode=kZLahu" rel="noopener noreferrer"&gt;Railway&lt;/a&gt; MySQL
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Why These Flags Matter
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;--no-tablespaces&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;JawsDB runs on AWS RDS, which restricts certain privileges required for dumping tablespaces.&lt;/p&gt;

&lt;p&gt;This flag avoids that issue.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;--set-gtid-purged=OFF&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Prevents replication metadata from causing conflicts during import.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;--single-transaction&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Creates a &lt;strong&gt;consistent snapshot&lt;/strong&gt; of the database while exporting.&lt;/p&gt;

&lt;p&gt;This works well for &lt;strong&gt;InnoDB tables&lt;/strong&gt;, which most Rails apps use.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Streaming the Database Is Powerful
&lt;/h2&gt;

&lt;p&gt;The pipe (&lt;code&gt;|&lt;/code&gt;) streams the SQL output directly into Railway.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;JawsDB → mysqldump → pipe → Railway MySQL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No intermediate dump files&lt;/li&gt;
&lt;li&gt;Faster migration&lt;/li&gt;
&lt;li&gt;Lower disk usage&lt;/li&gt;
&lt;li&gt;Works well for large databases&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 3: Verify the Migration
&lt;/h2&gt;

&lt;p&gt;After the import, verify the migration with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;railway run &lt;span class="nt"&gt;-s&lt;/span&gt; MySQL mysql &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-h&lt;/span&gt; &lt;span class="nv"&gt;$MYSQLHOST&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="nv"&gt;$MYSQLUSER&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-p&lt;/span&gt;&lt;span class="nv"&gt;$MYSQLPASSWORD&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nv"&gt;$MYSQLDATABASE&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"SHOW TABLES;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the migration worked correctly, you should see your tables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;users
transactions
posts
comments
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 4: Update Rails Configuration
&lt;/h2&gt;

&lt;p&gt;Previously, my Rails app used the JawsDB &lt;code&gt;DATABASE_URL&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://railway.com?referralCode=kZLahu" rel="noopener noreferrer"&gt;Railway&lt;/a&gt; automatically provides environment variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MYSQLHOST
MYSQLPORT
MYSQLUSER
MYSQLPASSWORD
MYSQLDATABASE
MYSQL_URL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The simplest Rails configuration is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;production&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;adapter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql2&lt;/span&gt;
  &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;%= ENV['MYSQL_URL'] %&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After pushing the code, &lt;a href="https://railway.com?referralCode=kZLahu" rel="noopener noreferrer"&gt;Railway&lt;/a&gt; automatically redeployed the application.&lt;/p&gt;




&lt;h2&gt;
  
  
  Heroku vs Railway (Quick Comparison)
&lt;/h2&gt;

&lt;p&gt;Here’s a quick comparison based on my experience migrating a small Rails API.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Heroku + JawsDB&lt;/th&gt;
&lt;th&gt;Railway&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Hosting model&lt;/td&gt;
&lt;td&gt;App dynos + add-ons&lt;/td&gt;
&lt;td&gt;App + services in one platform&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database&lt;/td&gt;
&lt;td&gt;JawsDB MySQL add-on&lt;/td&gt;
&lt;td&gt;Native managed MySQL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost (small project)&lt;/td&gt;
&lt;td&gt;~$20/month&lt;/td&gt;
&lt;td&gt;~$6/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deployment&lt;/td&gt;
&lt;td&gt;Git push&lt;/td&gt;
&lt;td&gt;Git push / GitHub integration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Environment variables&lt;/td&gt;
&lt;td&gt;Supported&lt;/td&gt;
&lt;td&gt;Supported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CLI tools&lt;/td&gt;
&lt;td&gt;Heroku CLI&lt;/td&gt;
&lt;td&gt;Railway CLI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database migration&lt;/td&gt;
&lt;td&gt;Manual dump/import&lt;/td&gt;
&lt;td&gt;Easy via &lt;code&gt;railway run&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Infrastructure management&lt;/td&gt;
&lt;td&gt;Managed&lt;/td&gt;
&lt;td&gt;Managed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Static outbound IP&lt;/td&gt;
&lt;td&gt;Not guaranteed&lt;/td&gt;
&lt;td&gt;Not guaranteed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best suited for&lt;/td&gt;
&lt;td&gt;Mature production apps&lt;/td&gt;
&lt;td&gt;Side projects &amp;amp; small apps&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Heroku still offers one of the best developer experiences.&lt;/p&gt;

&lt;p&gt;But for &lt;strong&gt;small projects or side tools&lt;/strong&gt;, simplifying infrastructure and reducing costs can make sense.&lt;/p&gt;

&lt;p&gt;For my Rails API, moving to &lt;a href="https://railway.com?referralCode=kZLahu" rel="noopener noreferrer"&gt;Railway&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;simplified my stack&lt;/li&gt;
&lt;li&gt;reduced hosting costs by ~70%&lt;/li&gt;
&lt;li&gt;required minimal migration effort&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're running a &lt;strong&gt;small Rails project with MySQL on Heroku&lt;/strong&gt;, exploring &lt;a href="https://railway.com?referralCode=kZLahu" rel="noopener noreferrer"&gt;Railway&lt;/a&gt; might be worth considering.&lt;/p&gt;




&lt;h2&gt;
  
  
  Question for Other Developers
&lt;/h2&gt;

&lt;p&gt;If you're hosting side projects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Are you still using Heroku?&lt;/li&gt;
&lt;li&gt;Or have you moved to platforms like &lt;a href="https://railway.com?referralCode=kZLahu" rel="noopener noreferrer"&gt;Railway&lt;/a&gt;, Fly.io, or Render?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'd love to hear what your stack looks like.&lt;/p&gt;

</description>
      <category>rails</category>
      <category>devops</category>
      <category>mysql</category>
      <category>heroku</category>
    </item>
  </channel>
</rss>
