Cloud Migration for a Custom Application: What Moves and How to Cut Over
Maybe your hosting company sent a notice that the server your app lives on is reaching end of life. Maybe the person who set up the box left two years ago, and nobody wants to be the one who reboots it. Either way, cloud migration has landed on your list, and when you search for it, most of what comes back is written for a different problem. The typical small-business cloud migration guide is about moving email, shared files, and backups into hosted services, usually with a managed IT provider doing the work. That’s useful if your problem is a file server in a closet, but it doesn’t help much when the thing you need to move is the custom application your business runs on, with a real database, real users, and jobs running in the background at three in the morning.
This page is about that second case. We’ll walk through the decision you have to make first, everything that has to move besides the code, how to switch over without taking the app down, and the signs that tell you it’s time to move instead of patching the old setup one more time.
What cloud migration means when the thing moving is an app
When the thing moving is a mailbox, migration mostly means copying data from one place to another and pointing people at a new login. An application is a running system. It has code that has to build and boot in a new environment, a database that keeps changing while you copy it, scheduled work that has to run exactly once, files your users uploaded, credentials for every service it talks to, and a domain name whose address is cached all over the internet. Moving the app means moving all of those together, in an order that keeps it working for the people using it the whole time.
That’s why app migrations go wrong in ways infrastructure checklists don’t anticipate. The code itself usually comes across fine, so the trouble tends to show up in the pieces around it: a cron job that silently stopped running on the new host, a folder of uploaded PDFs that stayed behind on the old disk, or an environment variable that existed on one server and that nobody ever wrote down.
Rehost, replatform, or rebuild: the decision that comes first
Before any of the mechanics, you have to decide how much of the app changes during the move. The industry terms for the options are rehosting, replatforming, and refactoring (which in practice usually means rebuilding), and each is easy enough to follow once you strip the jargon off.
Rehosting, sometimes called lift-and-shift, means running the same app, mostly unchanged, on new infrastructure. It’s the fastest path, and when the old host is the only problem it’s also the least risky. If your app is reasonably current and the issue is that the hosting company is ending support, this is usually where to start.
Replatforming means making targeted changes so the app fits a better home. A common example is moving off a hand-managed server onto a platform host like Render or Heroku, where the platform handles deploys, logs, and scaling, so they no longer depend on whoever last logged into the box. The code changes a little, mostly in how it reads its settings, where it keeps uploaded files, and how its background workers start, but the people using the app shouldn’t see any difference.
Rebuilding means rewriting significant parts of the application as part of the move. Occasionally that’s the right call, usually when the app is built on a framework version so old that nothing modern will run it. Combining a rewrite with a host migration stacks two large risks on top of each other, though, so we’d almost always separate them: get the existing app running somewhere stable first, then decide about the rewrite once the pressure is off.
The right choice depends on what the old host is actually costing you. If the cost is an end-of-support date, rehost. If the cost is that nobody on the team understands how the server is put together, replatforming onto a managed host removes that knowledge gap along with the server. If the app itself can’t run on anything current, you have an upgrade problem in addition to a hosting one, and our Rails end-of-life schedule is a good place to see how far behind you are.
What has to move besides the code
Most guides skip this part, but it’s where most of your planning time should go. Before you touch anything, write down each of these for your app.
The database is the hardest piece because it keeps changing. You need to know its size, its engine and version, and how long a full copy takes. A small database can be dumped and restored during a short pause, while a large one needs replication from the old server to the new one so the copy stays current until you switch.
Background jobs and queues come next. Most real applications send email, process uploads, or sync with other systems outside the normal page request, so find out what runs the jobs, where the queue lives, and what happens to jobs that are halfway done when you switch.
Scheduled tasks are the item people forget most often. List every cron entry on the old server with what it does and when it runs, and make sure each one runs on exactly one host at a time during the transition. A nightly billing job that runs twice causes far more trouble than one that runs an hour late.
File storage catches a lot of teams out. If users upload files and those files are saved to the server’s own disk, they have to move too, and the new host may not offer a persistent disk at all. This is often a good time to move uploads to object storage, which is a small code change you’ll want to make before the migration rather than in the middle of it.
Secrets and settings tend to be scattered. API keys, database credentials, mail settings, and payment provider keys often live in a mix of environment variables, config files, and someone’s memory, so collect them into one place and confirm which ones differ between staging and production.
DNS records finish the list. Your domain points at the old server’s address, and resolvers across the internet have cached that address. Check whether your mail records or any third-party verification records reference the old host as well, since those tend to break quietly.
How to cut over without a maintenance-window outage
The goal is a switch your users don’t notice, and you can start working toward it several days before the move.
Lower your DNS time-to-live well ahead of time. The TTL tells resolvers how long to cache your domain’s address, so if it’s set to a day, a change can take a day to reach everyone. If you drop it to a few minutes a couple of days in advance, traffic follows quickly when you change the record, and it follows back just as quickly if you need to switch back.
Run both environments side by side. Stand the new environment up completely, with the app deployed, workers running, and a copy of the data, while the old one keeps serving users, and test the new one against real data through a temporary hostname. People call this a blue/green setup. There are two complete environments and only one is live at a time, so switching between them comes down to changing where traffic goes.
Keep the data in sync until the switch. For a database that can’t be copied during a short pause, set up replication from old to new so the new database trails the live one by seconds. At cutover you stop writes briefly, let replication catch up, promote the new database, and point the app at it. The pause lasts seconds or a few minutes, and if the app retries requests sensibly, users see a page load slowly for a moment and never get an error.
Write down the rollback before you need it. Decide in advance what failure means for your app, whether that’s a jump in error rates, a failed health check, or a job that didn’t run. Then write out the exact steps that put traffic back on the old setup, and keep the old servers intact for at least a few days after the move so those steps still work if something surfaces late.
Automated tests do a lot of quiet work here. An app with a strong test suite can be deployed to the new host and checked in minutes, while an app without one needs someone to click through every screen by hand before anyone trusts it. The coverage standard we hold client projects to is on our existing products page.
The platforms we run applications on
We run client applications on the kinds of platforms this page describes. The Wine Spies runs on Render, another client application runs on Heroku, and eclipticideas.com itself is a Rails 8 application deployed to Render. We deliver major Rails and Ruby upgrades with zero downtime, and the approach carries straight over to a host move: the new environment gets built next to the old one and checked before any traffic reaches it, and the old one stays available as a way back until the new setup has run cleanly for a while.
If your migration is tangled up with an old framework version, our guide to upgrading Rails 6 to 7 covers the upgrade side, which usually goes best as its own project before or after the move.
Signs it’s time to move instead of patching
Plenty of hosting setups can be patched along for another year without much harm, but the situations below usually can’t.
Your host has announced an end-of-support date for the server, operating system, or plan you’re on. Once that date passes, security fixes stop arriving, and your business is running on software nobody is maintaining.
Nobody on the team can safely change the server. If deploys depend on one person’s memory, or everyone avoids restarting the machine because they aren’t sure it will come back, you’re already carrying the risk whether you migrate or not. On a managed platform, that knowledge lives in configuration anyone on the team can read.
You’ve hit a scaling wall. If adding capacity means buying a bigger server and moving everything onto it by hand, every growth spurt turns into a small migration. On a platform where capacity is a setting, the same change takes an afternoon.
The app can’t run on anything current. If the operating system or language version your app needs is no longer offered by modern hosts, the migration and an upgrade are tied together and you’ll want to plan both. Our post on Rails maintenance economics covers how to weigh the cost of that work against the cost of leaving things as they are.
Where to start on your own app
Before you talk to anyone, take an hour and build the inventory from the section above for your own application: the database size and version, every background job and scheduled task, where uploaded files live, every secret and where it’s kept, and your current DNS TTL. Any line you can’t fill in points to a real risk in your migration, and the finished list is the most useful thing you can bring to a planning call. If you’d like a second set of eyes on it, our week-one codebase audit describes how we review an inherited application, and you can book an intro call to walk through yours.