Migrate from Railway to Render

Bring your Railway apps and data to the Render platform.

Welcome! Let's move your Railway apps and datastores over to Render. You'll learn:

  • How Railway concepts translate to the Render platform
  • How to recreate your Railway services on Render
  • How to move your Railway datastores to Render Postgres and Key Value instances

If you hit any bumps, don't hesitate to contact our support team at support@render.com.

Why migrate?

Developers who switch from Railway to Render consistently find benefits in the following areas:

  • Reliable infrastructure: Many developers who move from Railway to Render cite reliability as a primary reason for switching, and report improved uptime after migrating. Render provides zero-downtime deploys by default, managed databases with built-in failover, and no resource contention between plan tiers.
  • Predictable pricing: Render's fixed instance types make costs easy to forecast, compared to Railway's per-minute vCPU/RAM billing that can fluctuate.
  • Fully managed datastores: Render Postgres includes point-in-time recovery, read replicas, and high availability out of the box. Railway's database templates are unmanaged Docker containers that you must maintain yourself.
  • Native log streaming: Render log streams send your logs directly to providers like Datadog, Grafana Cloud, and others. Railway lacks native log drain support.
  • Built-in DDoS protection: Every Render service includes DDoS mitigation at no extra cost.
  • No deployment pausing: Railway might pause deployments for Free and Hobby users during high-traffic periods. Render does not pause deployments based on platform load.

Concept mapping

Railway and Render share many of the same concepts (projects, services, custom domains, cron jobs), so much of the platform will feel familiar. Here are the key differences to keep in mind:

  • Compute model: Railway's compute is usage-based, where each service autoscales up to your plan's vCPU and RAM limits. On Render, you select a fixed with defined CPU and RAM.
  • Configuration: Railway splits configuration across service variables, shared variables, and reference variables (using ${{ }} template syntax). On Render, you use and environment groups.
  • Datastores: Railway databases are unmanaged Docker containers backed by volumes. Render provides fully managed and datastores with built-in backups and high availability.

For a full feature-by-feature comparison, expand the mapping below:

Show terminology mapping
Compute
RailwayRender

Service

Service

Usage-based compute (vCPU/RAM per plan)

(Free, Starter, Standard, etc.)

Service with public domain

Service without public domain

Cron job (scheduled service)

Service variables

Shared variables

Environment groups

Deployment
RailwayRender

Railpack auto-build / custom build command

Custom start command / Procfile web process

Pre-deploy command

Healthcheck endpoint

Health check path

Zero-downtime deploys (deployment overlap)

Zero-downtime deploys

This is the default behavior for Render services.

GitHub auto-deploy on push

Auto-deploy on push

Environments (production, staging, PR)

Preview environments

Storage
RailwayRender

Volumes (persistent storage mounted to a service)

Disks (persistent storage mounted to a service)

Networking
RailwayRender

Private networking (*.railway.internal)

Private network

Railway-provided domain (*.railway.app)

Render subdomain (*.onrender.com)

Custom domains

Custom domains

Observability
RailwayRender

Log Explorer / deployment logs

Log streams

Webhooks (Discord, Slack)

Notifications

Datastores
RailwayRender

Railway PostgreSQL (template)

(fully managed)

Railway Redis (template)

(fully managed, Redis®-compatible)

Infrastructure as Code
RailwayRender

railway.json / railway.toml

render.yaml (Blueprint)

1. Prepare to migrate

Now, let's make sure you have all the accounts and app details you need to migrate successfully.

Create your Render account

Signing up is fast and free:

Sign up for Render

Catalog your Railway resources

Open your Railway project and note the following for each service:

  • Service type: Does the service have a public domain (web service), no public domain (background worker), or a cron schedule (cron job)?
  • Build and start commands: Find these in your Railway service's Settings tab under Build and Deploy. If your repo includes config files such as railway.toml, railway.json, railpack.json, or a Procfile, note any relevant commands there as well.
    • On Render, each distinct process (e.g., web, worker) becomes a separate service.
    • The start command for each process serves as the corresponding Render service's .
  • Pre-deploy command (if any): Found in service Settings under Deploy.
  • All service variables and shared variables (i.e., )
    • Pay special attention to reference variables that use Railway's template syntax (e.g., ${{ Postgres.DATABASE_URL }}). You'll replace these with actual Render datastore URLs later.
  • Attached databases: Any PostgreSQL and Redis® database services in the project

2. Recreate your app on Render

Next, let's spin up Render resources that correspond to your Railway services and datastores.

Create datastores

We recommend creating any necessary Render Postgres and Key Value instances before you deploy the apps that use them. This way, your apps can connect to those datastores on their very first deploy.

We won't move your existing data from Railway to Render yet.

We'll do this as part of the final migration process.

Follow these steps for each Railway PostgreSQL and Redis database service you want to move:

  1. In the Render Dashboard, click New > Postgres or New > Key Value:

    Creating a new datastore in the Render Dashboard

  2. Specify the following:

    • Your datastore's name
    • The where you want to host the datastore
    • Which to run on
      • Free instance types are available for Render Postgres and Key Value to help you get started. See details.
    • Your starting storage (Postgres only)
      • Feel free to start with a small amount of storage (1 GB or 5 GB) for testing. You can increase a database's storage later, but only once every 12 hours.
  3. Click the Create button.

    Render provisions your new datastore, and it becomes available within a minute or two.

  4. After your datastore becomes available, open its Info page in the Render Dashboard and click the Connect dropdown in the top right:

    Viewing a database's internal URL

  5. Copy your datastore's internal URL. Your Render services will use this URL to connect to the datastore over a private network.

    • External clients (like your local development environment) can instead connect to the datastore via its external URL, which is available in the same dropdown.
  6. Repeat this set of steps for each Railway PostgreSQL and Redis database service you want to move.

Create services

Let's look at how to recreate your Railway services on Render.

Web services

If your Railway service has a public domain assigned, it receives HTTP traffic from the internet. On Render, this corresponds to a . Every web service receives an onrender.com subdomain, and you can add your own custom domains.

  1. In the Render Dashboard, click New > Web Service:

    Creating a new web service in the Render Dashboard

  2. Specify the following:

    • Your project repo and branch to deploy (from GitHub, GitLab, or Bitbucket)
    • Your app's language (Node.js, Python, etc.)
    • The where you want to host the service
      • Choose the same region as your datastores to enable low-latency private network communication.
    • Which to run on
  3. Provide the commands that Render will use to build and run your code:

    CommandValue

    Provide the same build command from your Railway service settings. Common examples include npm install for Node.js or pip install -r requirements.txt for Python.

    If your Railway service used Railpack's auto-detected build command, provide the equivalent command explicitly.

    (optional)

    Provide the same pre-deploy command from your Railway service settings, if any.

    Like Railway, Render runs the pre-deploy command before each deploy of your service. Use it to run database migrations and other setup tasks.

    Provide the same start command from your Railway service settings.

    Common examples include npm run start for Node.js and gunicorn your_application.wsgi for Python.

    Here's an example of these commands for a Node.js app:

    Setting deploy-related commands in the Render Dashboard

  4. Set any required environment variables for your web service:

    • For datastore connections, provide the internal datastore URLs you copied earlier.
      • On Railway, these are often set via reference variables like ${{ Postgres.DATABASE_URL }}. On Render, set DATABASE_URL and REDIS_URL directly to your Render datastore internal URLs.
    • For service-to-service communication, Railway uses service-name.railway.internal. On Render, services in the same private network communicate via service-name:port with no internet roundtrip.
    • For other environment variables, copy over the values from your Railway service variables and shared variables.
    • You can make changes to your service's environment variables at any time after your service is created. See details.
  5. If your Railway service had a healthcheck endpoint configured, set the same path under your Render service's Health Check Path setting. Render pings this path and waits for a 200 response before routing traffic to a new deploy.

  6. If your Railway service used a volume for persistent storage, add a Render Disk to your service. Specify the same mount path you used on Railway. Note that Render Disks are per-service and not shared across services.

  7. Click Deploy Web Service.

You're all set! Render kicks off your service's first deploy. You can view the build logs in the Render Dashboard.

When the deploy completes, your service is live at its onrender.com subdomain. If you encounter any issues, see Troubleshooting Deploys.

Background workers

If your Railway service runs continuously without a public domain (for example, a queue processor), this corresponds to a Render :

Creating a new background worker in the Render Dashboard

The steps for creating a background worker are similar to those for creating a web service. The key differences are:

  • Your background worker probably doesn't need to run a if your web service already handles database migrations.
  • Render does not provide a free instance type for background workers.

Complete the background worker creation process for every Railway service that runs without a public domain, specifying the appropriate build and start command for each.

Cron jobs

If your Railway service is configured with a cron schedule, it corresponds to a Render . Railway and Render both use standard crontab expressions for scheduling.

In the Render Dashboard, click New > Cron Job and provide the same schedule and start command from your Railway service settings.

Services do not share environment variables by default.

If your web service and background workers require some of the same environment variables, you can do one of the following:

  • Manually set the environment variables for both services
  • Create an environment group and apply it to both services

3. Swap over to your Render infrastructure

With everything up and running on Render, we're ready to move your data and DNS configuration over from Railway.

This final step (moving your data and DNS configuration) requires downtime for your app, even if brief.

Schedule your migration for off hours to minimize the impact on your users.

Scale up your Render datastores

Before you move over your data, make sure your Render Postgres and Key Value instances have sufficient storage and compute resources to handle your current requirements. You can upgrade as needed in the Render Dashboard.

Render Postgres

Render Key Value

  • You can upgrade your instance type at any time. Your Key Value instance is unavailable for a few minutes during the change.
  • You can't downgrade your instance type.

Stop your Railway services

Railway does not have a built-in maintenance mode. To stop your services from accepting traffic during the migration:

  1. In the Railway Dashboard, click on each service to open it.
  2. Find the active deployment and open its 3-dot menu.
  3. Click Remove to stop the deployment.

This stops your service entirely. Repeat for each service in your Railway project.

Removing a deployment stops all traffic to that service.

Unlike a maintenance mode, Railway does not display a maintenance page. Requests to your Railway domain fail until you either redeploy on Railway or point your DNS to Render.

Export data from Railway Postgres

  1. Confirm that TCP Proxy is enabled on your Railway Postgres service (it's enabled by default for Railway database templates).

  2. Get your public database connection URL.

    In the Railway Dashboard, open your Postgres service and find the DATABASE_PUBLIC_URL variable.

  3. Create a backup of your database.

Import data into Render Postgres

  1. Obtain your Render Postgres database's External Database URL from its Info page in the Render Dashboard.

  2. Import railway_backup.dump into your Render Postgres database.

For large databases, consider using the --jobs flag with both pg_dump and pg_restore to speed up the process.

For example, pg_dump --jobs 4 and pg_restore --jobs 4 run four parallel workers.

Export and import Railway Redis data

If you're migrating a Railway Redis service to Render Key Value:

  1. Confirm that TCP Proxy is enabled on your Railway Redis service.

  2. Get your Railway Redis public connection URL from the Redis service's variables (REDIS_URL with the TCP Proxy host and port).

  3. Use redis-cli to export your data and import it into your Render Key Value instance:

  4. Import the data into your Render Key Value instance using the Render Key Value external connection URL from the Render Dashboard:

    Alternatively, if your dataset is small, you can use the DUMP and RESTORE commands to transfer keys individually.

Update your DNS records

If your Railway service uses a custom domain, follow the instructions to update your DNS configuration to point to Render instead of Railway. Apply each app's custom domain to the corresponding Render web service.

Note that it takes some time for your DNS changes to propagate, and for Render to then provision a TLS certificate for your domain.

Troubleshooting

If you run into issues during your migration, check the following first:

  • Database connections fail: Replace Railway reference variables like ${{ Postgres.DATABASE_URL }} and ${{ Redis.REDIS_URL }} with the actual internal URLs for your Render datastores.
  • Your build fails on Render: Railway's Railpack often auto-detects build behavior. On Render, you might need to specify an explicit build command.
  • Your app can't find persisted data: Confirm that your Render Disk mount path matches the path your app used on Railway.
  • Your app doesn't start listening for traffic: Make sure your app listens on the PORT environment variable that Render provides.

For more help with general deploy issues, see Troubleshooting Deploys.

Next steps

Congratulations! You've successfully migrated your Railway app to Render.

Next, explore more of Render's capabilities. Here are a few to get you started: