To plan a migration off Railway, inventory your services and their dependencies, choose a destination for each component, and rehearse data transfers before switching traffic. Move independently where connections allow it. Coordinate components that share data or jobs, and define how you'll preserve new writes if you need to roll back.
The unit of migration is often smaller than the project. You might move a frontend and API while keeping a database in place, then move the worker once its queue and files are reachable from the new host. If you're still choosing a destination, compare Railway alternatives by application need before scheduling the move.
Copy link to headingWhat should your Railway migration plan contain?
Your migration plan needs to explain how the application will work at each stage, including the period when services run on different platforms. Destination URLs alone won't tell you whether the new worker can read a file written by the old API.
Consider a document-processing application with a web frontend, a Python API, and a worker that extracts text from uploaded files:
Record an owner and a success condition for each component. For the extraction worker, verify that it processes a queued document and makes the result visible through the API. Starting the process alone doesn't establish success.
Copy link to headingWhat needs its own migration decision?
Some changes alter the application's behavior enough to deserve a separate test and release. Moving files from a mounted directory to object storage changes file access. Replacing a queue can change acknowledgment and retry behavior. Runtime upgrades may change which dependencies install successfully.
Keep unrelated changes out of the cutover where possible. When a change is required, test it on the current deployment or in an isolated environment before combining it with the platform move. This gives you a known working version to compare with the destination.
Copy link to headingHow do you prepare the move?
Copy link to heading1. Capture the working configuration
Confirm access to the source repository, Railway project settings, and destination account. You'll also need database credentials with the required export permissions and control over the application's DNS records. Record the currently deployed commit so you can reproduce the version serving users.
Capture build and start commands, runtime versions, and any release commands that run database migrations. Include volume mount paths and scheduled tasks. Check the deployed settings against the repository, because the running service may depend on configuration that isn't committed with the code.
Railway reference variables can point to values in other services. The expression ${{Postgres.DATABASE_URL}} refers to the DATABASE_URL variable on the Postgres service. At the destination, configure the connection the application will use rather than copying that expression unchanged.
For credentials, record where each value comes from and which service needs it. Railway's sealed variables aren't available through CLI exports, so retrieve the original value from its owning system or issue a replacement there. Keep production credentials separate from the values used for migration tests.
Copy link to heading2. Choose a sequence that preserves dependency access
Choose the first component based on what it can reach after moving. The frontend can move independently if its API remains accessible and authentication works from the new origin. An API may need its storage moved first if a worker and the API currently share local files.
Railway private networking connects services within a project environment. An address ending in .railway.internal won't become a usable external connection because you copied it into another host's environment variables. Verify the required endpoint, authentication, and transport security from the destination.
For the document-processing example, a possible sequence is to prepare shared object storage, update the existing API and worker to use it, and then move the API. The worker can follow once it can reach the queue and write results to the database. Moving PostgreSQL can remain a separate operation if every process has an acceptable connection to it.
This order depends on the application. If queued jobs contain absolute paths to files on the old volume, account for those jobs before switching the worker. You may need to finish them first or translate their file references.
Copy link to heading3. Rehearse the database and file transfers
For every dataset that moves, restore representative data into an isolated destination and check for missing extensions or permissions. Measure transfer and verification time during the rehearsal to plan the production window.
For PostgreSQL, a custom-format export with pg_dump can be restored with pg_restore. Use clients that support both database versions.
Prepare a new, empty rehearsal database and set SOURCE_DATABASE_URL and REHEARSAL_DATABASE_URL in a private shell session. The destination must be a disposable test database, separate from the source and production destination.
Run this Bash example to export and restore your database. The archive contains application data, so keep it in restricted storage and out of version control:
set -euo pipefail
: "${SOURCE_DATABASE_URL:?Set the source PostgreSQL connection URL}": "${REHEARSAL_DATABASE_URL:?Set a new empty rehearsal database URL}"
umask 077backup_dir="$(mktemp -d)"
pg_dump \ --dbname="$SOURCE_DATABASE_URL" \ --format=custom \ --file="$backup_dir/railway.dump"
pg_restore \ --dbname="$REHEARSAL_DATABASE_URL" \ --no-owner \ --no-privileges \ --exit-on-error \ "$backup_dir/railway.dump"The pg_restore options omit the original ownership and access grants and stop on an error. Configure the destination's application role and permissions deliberately. If restoration fails, inspect the error and repeat against a fresh empty rehearsal database after fixing the cause.
Verify business data after restoration. For the document application, check document records against their extracted text and confirm that stored file references still resolve. Exercise the application against the restored database with outbound email and other external effects disabled or directed to test systems. Delete the temporary archive after the rehearsal when you no longer need it.
An export captures a database snapshot. Writes made afterward need a separate plan: pause all writers for the final transfer, or use a replication process supported by the source and destination. Include workers and scheduled jobs in that decision, since stopping web requests doesn't stop every database write.
Copy uploaded files with their application references intact. Verify object counts and checksums where available, and arrange a final synchronization that accounts for files added, changed, or deleted during the initial copy. Documents can remain unreadable after a successful database restore if their files never arrived.
Copy link to heading4. Test the whole application on the destination
Use isolated databases, queues, and file storage for the trial. The trial deployment could consume real jobs if you connect it to a production queue.
For the document application, test uploading a file and submitting it for extraction. Follow the job through the worker, then fetch the result from the API. Also check authentication and permissions with more than one test user, so successful processing doesn't hide an access-control error.
Exercise failure paths that affect stored work. Restart a worker during a job and check whether it finishes, retries, or leaves a recoverable record. Test how the application handles a temporarily unavailable dependency. Define the result you require before the rehearsal, including how repeated delivery avoids applying the same business action twice.
On Vercel, separate application previews from continuous-worker testing. Daemons run only in Production during the beta, so start by running the worker image locally against isolated dependencies.
Then repeat the trial with a deployed Daemon in a separate Vercel project using isolated resources. Since a new project's first deployment uses the Production environment, configure test credentials before deploying.
Copy link to heading5. Define rollback before accepting new writes
Separate application rollback from data rollback. If the database stays in place and the schema remains compatible, the old application may be able to resume against the same records. If the database moves, writes accepted by the new database won't automatically appear in the old one.
For that second case, decide whether rollback means running the old application against the new database or stopping writes and reconciling data before switching back. Restoring yesterday's database backup would discard today's changes. Keep the source available, but don't resume production there with outdated data.
Platform deployment rollback has the same boundary. Vercel Instant Rollback can restore an earlier application deployment, but your plan still needs to account for database changes and external actions performed since that version ran.
Copy link to heading6. Coordinate the production handoff
Write a runbook with the order of actions, who performs them, and the condition that stops the move. It should identify when writes pause, when the final data check completes, and when the new application can accept traffic.
Make successful schema migration a prerequisite for releasing code that needs the new schema. During a staged move, both the old and new application may use the database. Add compatible fields first and delay removing old fields until the old code and any rollback version no longer depend on them.
For workers, decide how in-progress jobs finish and when the destination starts consuming. If old and new consumers overlap, they must understand the same job format and use the queue's supported delivery behavior. When replacing the queue too, plan to transfer or drain pending jobs before disconnecting the old system.
Assign each scheduled task to one scheduler during the handoff. Disable the old schedule as the replacement takes ownership, and record the last completed run. Check whether a missed run needs replaying and whether a repeated run could delete files or send duplicate notifications.
Verify the production deployment before changing DNS. Include callback URLs, webhook destinations, and cookie settings if an origin changes. Keep the old endpoint capable of handling any requests that continue to reach it during DNS propagation, or pause writes there when the data cutover requires it.
Copy link to headingWhere do you start a Railway-to-Vercel migration?
Choose an execution model for each process using the Vercel backends overview, then follow the Railway-to-Vercel migration guide to configure and deploy the application. For FastAPI, Flask, or Django, the Python API migration guide covers entrypoints and dependencies. Choose the worker path separately, since changing API hosting doesn't require changing the queue architecture at the same time.
Copy link to headingFrequently asked questions
Copy link to headingCan I migrate off Railway one service at a time?
Yes, if each migrated service can reach the dependencies it still uses and the old and new versions remain compatible. Shared files, private addresses, and queued job formats can require coordinated changes. Identify those connections before deciding the order of the move.
Copy link to headingIs a successful database export enough to switch hosts?
No. Restore the export into an isolated database and verify that the application can use it. You also need to handle writes that occur after the export and transfer any files stored outside the database.
Copy link to headingHow do I avoid running scheduled jobs twice during migration?
Assign the next run of each task to either the old or new scheduler and disable the other schedule during the handoff. Record the last successful run so you can identify gaps. Make repeated execution safe where possible, especially for tasks that send messages or modify data.
Copy link to headingHow long does a Railway migration take?
The duration depends on the application changes, data volume, and time required to verify the new deployment. Use a rehearsal to measure export, restore, and testing time before choosing a production window. Keeping the database in place creates a different schedule from moving it in a final transfer while writes are paused.
Copy link to headingWhen can I delete the old Railway resources?
Retire a resource after verifying that the migrated application no longer depends on it and that the agreed rollback period has ended. Check background jobs and scheduled tasks as well as web traffic. Preserve the backups you still need before removing the source data.