All posts

Moving from Railway or Render to Cloud Run

Railway and Render projects map to Google Cloud piece by piece. What each part becomes, the commands, the cost on each side, the order of the move, and when staying is the better answer.

Moving from Railway or Render to Cloud Run maps each piece to Google Cloud: a web service runs the same image on Cloud Run, a worker becomes Cloud Tasks, cron becomes Cloud Scheduler, the pre-deploy command a Cloud Run job, Postgres Cloud SQL and a volume a Cloud Storage bucket. Our small sample project costs $10.00 a month on Cloud Run, about $12 on Railway and $31.25 on Render.

In short

  • Of the $10.00 a month on Cloud Run, $9.37 is the smallest Cloud SQL instance; the services stay inside the free tier at 500 visitors a day.
  • Cloud Run's SLA promises 99.95% a month on every service with no plan to buy; Railway and Render offer contractual SLAs on Enterprise.
  • Cloud Run runs in 43 regions, Railway in 4 and Render in 5.
  • Render's paid instances run every hour, and its free web services take about a minute to wake after 15 minutes idle; a request-based Cloud Run service costs nothing between requests.

Prices are list prices read on October 12, 2026, with Cloud Run in europe-west1.

How each one bills today

Railway and Render are closer to Cloud Run than Heroku is: they build from a repository or a Dockerfile, a project of several services is their normal shape, and Railway already bills by the resources a service uses.

Railway charges a plan and the resources you use. The Hobby plan is $5 a month and includes $5 of usage; Pro is $20 and includes $20. On top of that, a service pays for the memory it holds, $10 per GB a month, the CPU it uses, $20 per vCPU a month, traffic out at $0.05 per GB and volumes at $0.15 per GB a month, all metered by the minute. Builds are free. A service that sits idle still holds its memory, so it still costs something, unless you turn on Railway's serverless mode, which puts a service to sleep 5 to 10 minutes after its last outbound traffic and wakes it on the next request.

Render charges a workspace plan and an instance per service. The Hobby workspace is free, Pro is $25 a month and Scale $499. A web service or a worker is $7 a month for half a CPU and 512 MB, $25 for one CPU and 2 GB. Paid instances run every hour; only free web services spin down, after 15 minutes without inbound traffic, and take about a minute to come back. A cron job is billed by the second with a $1 monthly minimum, Postgres starts at $6 a month, Key Value (Redis) at $10, a persistent disk is $0.25 per GB a month, and traffic out above the included 5 GB (Hobby) or 25 GB (Pro) is $0.15 per GB.

Cloud Run bills a service, with request-based billing, for the time its instances spend handling requests: in europe-west1, $0.000024 per vCPU-second, $0.0000025 per GiB-second and $0.40 per million requests, after a monthly free tier of 180,000 vCPU-seconds, 360,000 GiB-seconds and 2 million requests per billing account. A service with no traffic scales to zero and costs nothing; the cost guide works through every line.

When the move is worth it, and when it is not

Four reasons come up most often:

  • An uptime commitment in writing. Cloud Run's SLA promises 99.95% a month on every service, with no plan to buy (99.9% in Mexico and Stockholm). Railway's Pro plan states a 99.99% availability target, and a contractual SLA comes with its Enterprise offering; Render lists contractual uptime SLAs on its Enterprise plan.
  • Regions. Cloud Run runs in 43 regions. Railway has four (California, Virginia, Amsterdam, Singapore) and Render five (Oregon, Ohio, Virginia, Frankfurt, Singapore).
  • Paying nothing while idle on a paid service. Render's paid instances run every hour; Cloud Run's request-based services cost nothing between requests.
  • The rest of Google Cloud: Cloud SQL with point-in-time recovery, Cloud Storage, BigQuery, Pub/Sub and Gemini on one bill and one identity system.

The price alone is a weaker reason than it looks, as the cost section shows, because Cloud SQL's smallest instance costs more than a small Railway Postgres. If the app keeps a CPU busy all day, or holds thousands of open connections, stay where you are or take a server; Cloud Run or a VPS works out where the line falls. Exodus says so in its verdict when the numbers point that way.

What the CLI reads

Exodus's CLI reads railway.json or railway.toml, render.yaml, the Procfile, the Dockerfile, docker-compose.yml and your language's manifest (package.json, pyproject.toml, requirements.txt, Gemfile, Cargo.toml). Each service in them becomes a part of the report, with its start command, its variables and what it talks to. Here it is on the Render example from the CLI's open repository, a Django app with a web service, a Celery worker with a disk, a Redis and a Postgres:

A terminal with exodus audit reading render.yaml: the web, release and worker processes, the disk, Redis and Postgres, and three patterns that break, then exodus report saying the app can move after 3 changes
exodus 0.1.3 on a Render blueprint: every service and datastore with its line in render.yaml, and the three patterns that need a change first.

The report then prices both sides from list prices: $30.55 a month on Render for this blueprint and $10.00 on Cloud Run at 500 visitors a day. For the Railway example, an Express app with a BullMQ worker, a node-cron clock, Postgres, Redis and uploads on disk, it found four patterns to change and put Railway at $35.55 against $10.02. These "today" figures are the CLI's estimates from each platform's smallest paid sizes; once you answer its question about your current bill, the real figure replaces them.

What each piece becomes

A diagram mapping nine Railway and Render pieces to Google Cloud: web service to a Cloud Run service, worker to Cloud Tasks and a handler, cron to Cloud Scheduler, pre-deploy to a migrate job, Postgres to Cloud SQL, Redis often removed, volumes to Cloud Storage, shared variables to Secret Manager, the private network to HTTPS with ID tokens
Each piece of a Railway project or a Render blueprint and its place on Google Cloud.

A web service becomes a Cloud Run service. If it has a Dockerfile, the same image runs; if Railway or Render built it from source, Cloud Run can build it with Google's buildpacks from the same source. The service must listen on the port in $PORT (8080 by default), on 0.0.0.0.

A worker service that pulls jobs from Redis becomes Cloud Tasks calling a handler in the web service, one request per job, with retries and rate limits kept by the queue. Keep a worker pool, Cloud Run's resource for pull-based processes, for the rare worker that has to hold a loop, such as a stream consumer.

A cron job becomes Cloud Scheduler. Railway runs a service's start command on its cron schedule, at least 5 minutes apart, in UTC, and skips a run while the previous one is still active. Render's cron jobs also run in UTC and are stopped after 12 hours. A Scheduler job calls an endpoint for short work or starts a Cloud Run job for long work, and has its own time zone, so a schedule written for UTC can be set in local time.

The pre-deploy command (preDeployCommand in railway.json or render.yaml) becomes a Cloud Run job that runs the migration before the new revision takes traffic. On Railway it is not retried and has no time limit unless you set one; on Render it runs on a separate instance and a failure cancels the deploy. A job behaves like the second: it runs once, and your deploy script stops if it fails.

A Postgres becomes Cloud SQL for PostgreSQL, or a serverless Postgres outside Google when it is small. Railway's Postgres is a container with a volume; Render's is a managed instance. Either way the data moves with pg_dump and pg_restore.

A Redis or Key Value often goes away: sessions move to signed cookies, the queue to Cloud Tasks, a cache to memory or the database. Keep a managed Redis only when the app needs one for something else.

A volume or a persistent disk becomes a Cloud Storage bucket, read and written through the bucket's API rather than a path on disk. Both platforms already limit a service with a disk: Railway allows one volume per service and no replicas with it, Render allows one instance and no zero-downtime deploys. A bucket removes both limits.

Shared variables and environment groups become Secret Manager for secrets and plain environment variables for the rest. Railway's ${{shared.KEY}} references and Render's generateValue have no equivalent; each secret is created once and attached to the services that need it.

Private networking between services becomes HTTPS between Cloud Run services, with Google identity instead of a private address. Railway's services find each other at SERVICE.railway.internal; Render's on internal hostnames within one region. On Cloud Run the receiving service allows the caller's service account with the Cloud Run Invoker role, and the caller sends an ID token.

The commands

The sequence below deploys a web service with its secrets and database and a migrate job, in europe-west1. It assumes an image in Artifact Registry, a Cloud SQL instance named db, a secret database-url holding the connection string and a service account named web; the Heroku guide shows how to create each.

printf '%s' "$SESSION_KEY" | gcloud secrets create session-key \
  --data-file=-

gcloud run deploy web \
  --image="$IMAGE" \
  --region=europe-west1 \
  --service-account="web@$PROJECT.iam.gserviceaccount.com" \
  --add-cloudsql-instances="$PROJECT:europe-west1:db" \
  --set-secrets="SESSION_KEY=session-key:latest,DATABASE_URL=database-url:latest" \
  --allow-unauthenticated

gcloud run jobs create migrate \
  --image="$IMAGE" \
  --region=europe-west1 \
  --service-account="web@$PROJECT.iam.gserviceaccount.com" \
  --set-cloudsql-instances="$PROJECT:europe-west1:db" \
  --set-secrets="DATABASE_URL=database-url:latest" \
  --command=npm \
  --args=run,migrate

gcloud run jobs execute migrate \
  --region=europe-west1 \
  --wait

The secret's value goes in through a pipe, so it never appears in the shell's history or the process list. For a private service that another one calls, the receiving side grants the caller:

gcloud run services add-iam-policy-binding reports \
  --region=europe-west1 \
  --member="serviceAccount:web@$PROJECT.iam.gserviceaccount.com" \
  --role=roles/run.invoker

and the caller gets an ID token for the receiving service's URL from the metadata server and sends it as a bearer token. Tokens last about an hour; the client libraries fetch and refresh them for you.

curl -s -H "Metadata-Flavor: Google" \
  "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=$REPORTS_URL"

One service or several

A Railway project or a Render blueprint often has three or four services because the platform made that cheap to express. On Cloud Run the worker usually folds into the web service as handlers, and the cron service disappears into Scheduler. Many projects end as one service, one job and a few Scheduler entries.

Cloud Run can deploy a Compose file with gcloud run compose up, generally available since March 25, 2026, but it does not do what a Railway project does. It deploys the whole file as one Cloud Run service with several containers in it, set to at most one instance by default, and Google recommends it for development and Terraform for production. For services that scale on their own, deploy one image per service from CI, as above.

Sleeping services and cold starts

Render's free web services spin down after 15 minutes without traffic and take about a minute to come back; its paid services never sleep. Railway's serverless mode sleeps a service after 5 to 10 minutes without outbound traffic, and Railway warns that the first request to a sleeping service may get a 502.

Cloud Run scales a request-based service to zero by default and starts an instance when a request arrives; the request waits for that start and gets its answer, not an error. How long the start takes depends on the container. Exodus team: a small Rust API of ours had a median instance startup of 94 ms over a week in October 2026, and a generated Rails 8 app took about 3 seconds to its first answer in our local tests. If even that matters, keep one minimum instance; the minimum instances guide prices it.

What it costs on each side

Take a small project: a web service, a worker, a job once a day, Postgres, Redis and 1 GB of uploaded files, with modest traffic (500 visitors a day, 5 GB out a month).

  • Railway, Hobby: usage depends on what each service holds. Assume each of the four always-on services (web, worker, Postgres, Redis) holds 0.25 GB of memory and averages 2% of a vCPU: $2.50 + $0.40 = $2.90 each, $11.60 for four, plus two 1 GB volumes ($0.30) and 5 GB of egress ($0.25). Usage $12.15, of which the plan's $5 is included: $12.15 a month.
  • Render, Hobby workspace: web $7, worker $7, the cron job's $1 minimum, Postgres $6, Key Value $10 and a 1 GB disk $0.25: $31.25 a month, at list prices.
  • Cloud Run: the web service and the worker's jobs stay inside the free tier at this traffic, the daily job is free with Scheduler's three free jobs, 1 GB in a bucket is $0.02, images in Artifact Registry about $0.01, 5 GB of egress $0.60, and Cloud SQL db-f1-micro with 10 GB of SSD $9.37: $10.00 a month.
A bar chart of a small project for a month: Railway Hobby with usage $12.15, Render with paid instances $31.25, Cloud Run with Cloud SQL $10.00
The same small project at list prices: about $12 on Railway with the usage assumed in the text, $31.25 on Render, $10.00 on Cloud Run, of which $9.37 is the database.

The Railway figure moves with its assumption: double the memory each service holds and it is about $22. The Cloud Run figure barely moves with traffic at this size, because 94% of it is the database. So the honest summary is: compared with Render's paid instances, the move saves money for a small project; compared with Railway, it is about even, and the reasons to move are the ones above. A serverless Postgres from another provider can lower the Cloud Run line; the database choice guide compares them.

Our own small services are the other data point. Exodus team, October 2026, europe-west1, Google's bill after the free tier: an API on a document database $0.13 a month, an API, web app and worker on Postgres $9.79 (of which the database $9.34), five tiny services sharing a project $0.69, and $2.10 of one-off builds in the first days after a move. They are idle most of the day, and request-based billing charges nothing for idle. An app that is busy all day would not see that.

The order of the move

A diagram of four steps in order, change the code where it runs now, stand up Google Cloud beside it, rehearse the database copy, cut over, with the way back for each: before step 4 production stays put, after it the old project is kept for a few days
The order of the move: three steps that leave production where it is, then the cutover, with the old project kept as the way back.
  1. Change the code where it is today: the worker to handlers, files to a bucket, timers to endpoints, sessions to signed cookies. Each change deploys to Railway or Render and is tested there. The patterns guide goes through each one.
  2. Stand up Google Cloud beside it: the Cloud Run service, Cloud SQL, the secrets, the queue and the schedules, all at the service's run.app address while production stays where it is.
  3. Rehearse the database copy against a copy of production and time it. Railway's Postgres is reachable from outside through its TCP proxy, which bills its traffic as egress; Render gives each database an external URL next to the internal one, behind an IP allow list. Then:
pg_dump "$OLD_DATABASE_URL" \
  --format=custom \
  --no-owner \
  --no-acl \
  --file=app.dump
pg_restore \
  --dbname="$NEW_DATABASE_URL" \
  --no-owner \
  --no-acl \
  app.dump
  1. Cut over: freeze writes, take the final dump, restore it, compare row counts table by table, switch the domain, and keep the old project running, but not writing, for a few days as the way back. The cutover day checklist lists every check, and moving a Postgres database covers larger databases.

Where Exodus comes in

Exodus runs this move with your own coding agent. The CLI audits the repository on your machine, as above; the report prices your current platform against Cloud Run and lists the changes in order; the plan turns them into tasks, from the Dockerfile and the health check to the switch of the domain. Nothing signs in to Google Cloud for you: your agent uses your own gcloud.

FAQ

Is Cloud Run cheaper than Railway?

For a small project it is about even. Our sample project costs $10.00 a month on Cloud Run and about $12.15 on Railway's Hobby plan with the usage we assumed, or about $22 if each service holds twice the memory. 94% of the Cloud Run figure is the database, so the reasons to move are the SLA, the regions and Google Cloud.

Is Cloud Run cheaper than Render?

Against Render's paid instances, yes for a small project: the same sample costs $31.25 a month on Render and $10.00 on Cloud Run at list prices. Render's paid web services and workers run every hour, while a request-based Cloud Run service costs nothing between requests.

What replaces private networking between Railway or Render services?

HTTPS between Cloud Run services, with Google identity instead of a private address. The receiving service grants the caller's service account the Cloud Run Invoker role, and the caller sends an ID token from the metadata server. Tokens last about an hour, and the client libraries fetch and refresh them.

Can Cloud Run deploy a Compose file the way Railway runs a project?

Not the same way. Compose deploys, generally available since March 25, 2026, put the whole file into one Cloud Run service with several containers, at most one instance by default, and Google recommends them for development. For services that scale on their own, deploy one image per service from CI.

Do Cloud Run services sleep like Render's free web services?

A request-based Cloud Run service scales to zero, but the next request waits for an instance to start and gets its answer, not an error. A small Rust API of ours had a median instance startup of 94 ms; Render's free services take about a minute. One minimum instance removes the wait.

Sources

28
  1. docs.railway.comPlans and resource pricing, Railway docs
  2. railway.comPricing, Railway
  3. docs.railway.comSupport, Railway docs
  4. docs.railway.comRegions, Railway docs
  5. docs.railway.comCron jobs, Railway docs
  6. docs.railway.comServerless, Railway docs
  7. docs.railway.comPre-deploy command, Railway docs
  8. docs.railway.comConfig as code, Railway docs
  9. docs.railway.comVolumes, Railway docs
  10. docs.railway.comVariables and private networking, Railway docs
  11. render.comPricing, Render
  12. render.comDeploy for free, Render docs
  13. render.comCron jobs, Render docs
  14. render.comDeploys, Render docs
  15. render.comPersistent disks, Render docs
  16. render.comRegions, Render docs
  17. render.comOutbound bandwidth, Render docs
  18. cloud.google.comCloud Run pricing, Google
  19. cloud.google.comCloud Run SLA, Google
  20. docs.cloud.google.comCloud Run locations, Google
  21. docs.cloud.google.comDeploy services using Compose, Cloud Run docs, Google
  22. docs.cloud.google.comCloud Run release notes, Google
  23. docs.cloud.google.comAuthenticating service-to-service, Cloud Run docs, Google
  24. render.comCreate and connect to Render Postgres, Render docs
  25. docs.railway.comPostgres on Railway, Railway docs
  26. docs.cloud.google.comDeploy from source code, Cloud Run docs, Google
  27. cloud.google.comCloud SQL pricing, Google
  28. Exodus team: exodus 0.1.3 audit and report on the open CLI's Railway and Render examples; our own services' bills on Cloud Run and their instance start times, October 2026

Exodus moves your app to Cloud Run.

A free web cabinet and an open-source CLI. With your coding agent, they audit your app, show what it costs today and on Google Cloud Run, and move it there step by step.

Sign up for freeSee a sample report
  1. Install the CLIOne line in your terminal, once per machine.
  2. Give the prompt to your agentSign in with Google and copy one prompt. Your agent audits the app on your machine.
  3. Read the report, then moveThe bill today and on Cloud Run, what to change and in what order. The agent does the moving.

Read next

Consult an expert

For a move that is hard to make alone: many services, a large database, no room for downtime. An engineer who has moved production apps to Cloud Run reads what you send and replies by email.

Optional.

What the app does and what it runs on today.

Optional. Anything that would change the plan: compliance, regions, a contract that ends.

Your email goes to our engineers and nowhere else.