deplaneDocs Dashboard

Moving from Railway

Move a Railway service to Deplane with one command: deplane import railway reads the project on Railway, shows what moves and what stays, then creates the Deplane app with its secrets, workers, cron jobs and release command, copies the Postgres database, adds a Redis, and deploys your code. Railway keeps serving your users until you switch.

The command runs on your own computer with your Railway token, which never leaves it. It only reads Railway (GraphQL queries, never changes). The command and its flags are in the CLI reference, and every error has a fix in Troubleshooting and error codes. It works like Moving from Heroku, which explains the switch-over in more detail.

Before you start

  1. Install the Deplane CLI and run deplane login.
  2. Have the service's code in a folder: a checkout of the repository Railway deploys.
  3. Give Postgres a public address. Railway databases are private by default, and Deplane copies the database from outside Railway. Open the Postgres service → Settings → Networking → Public Networking and add a TCP Proxy. This sets DATABASE_PUBLIC_URL (a ...proxy.rlwy.net address), which the import reads. Without it the report has a ✗ line saying so. You can remove the proxy after the switch; Railway bills its traffic as egress.
  4. Create a project token: the project's Settings → Tokens, for the environment to import (usually production).

The Railway token. A project token reaches one environment of one project, and that is the environment the CLI imports. An account token works too (the CLI then imports the production environment, or the only one), but reaches every project you have. Workspace tokens are not supported yet: use a project token for a workspace's project. Railway has no read-only tokens; the CLI only reads with it. Delete the token when the import is done.

Give the token to Deplane in one of three ways, never as a flag:

A token piped on stdin wins over RAILWAY_TOKEN. The CLI says which one it used, never the token. It sends it only to Railway's API (backboard.railway.com), never writes or prints it, leaves it out of --debug, and never sends it to Deplane.

Which service

deplane import railway PROJECT imports the one service with a public domain. If several services have one, name it: deplane import railway my-project/web. The other services of the environment are sorted in the report:

Check first

$ deplane import railway shop --check
Railway service shop (project shop, environment production, region europe-west4-drams3a) → Deplane app shop

Processes
  ✓ web: shop, 2 replica(s) on Railway → 2 small instance(s).
  ⚠ Railway has no instance sizes (it bills by use): Deplane starts the app and its workers on small instances ...
  ✓ pre-deploy command → release command `npm run migrate`.
  ✓ worker: 1 replica(s) on Railway → worker worker, 1 small instance(s): `node worker.js`.

Data
  ✓ Postgres (Postgres): copied into a new Deplane database shop-db ... through its public URL ...
  ⚠ Redis (Redis): a new Deplane Redis shop-redis ... Its data is not copied ...

Config vars
  ✓ 2 copied as secrets: APP_URL, SECRET_KEY_BASE.
  ✓ Not copied, Deplane sets them: DATABASE_URL, PORT, REDIS_URL.
  ✓ Not copied, Railway-managed: RAILWAY_PUBLIC_DOMAIN.
  ⚠ Not copied, they read from the Postgres or Redis that Deplane replaces: PGHOST. Deplane sets only DATABASE_URL and REDIS_URL ...
  ⚠ Railway never returns sealed variables through its API, so any you sealed are not copied ...
...
Nothing was changed (--check). Run the command again without --check to import.

Then run the command again without --check (in a terminal it asks first; from a script, add --yes). The flags are the same as for Heroku: --source DIR, --name NAME, --check, --yes.

What moves

On RailwayOn Deplane
The serviceThe app, with as many instances as replicas, all small: Railway has no sizes. Change them with deplane scale.
Worker and cron services (see above)Workers and cron jobs, with their start command and schedule.
The pre-deploy commandThe release command.
Variables, resolved (shared variables and references included)Secrets. A worker's variables are added; where one sets a name differently, the web service's value is used and the report names it. Not copied: RAILWAY_*, PORT, and the variables that read from the Postgres and Redis Deplane replaces (such as PGHOST or PGPASSWORD: the report names them; Deplane sets only DATABASE_URL and REDIS_URL).
Postgres (DATABASE_URL = ${{Postgres.DATABASE_URL}})A new Deplane database, copied once from DATABASE_PUBLIC_URL (copy mode), attached as DATABASE_URL.
Redis (REDIS_URL = ${{Redis.REDIS_URL}})A new, empty Deplane Redis (Valkey 8, 256 MB), attached as REDIS_URL.
The codeYour folder, built by Railpack, or by your Dockerfile if it has one.

What does not move

Switch over

The first import is a rehearsal. When the Deplane app works:

  1. Before the day: deplane domains add HOSTNAME --app APP for each custom domain, and add the TXT record it shows. Make sure your plan has room for one more database.
  2. Stop writes on Railway: remove the active deployment of the service and of its workers (each service → Deployments → the active one → Remove). The site is down from here until DNS moves.
  3. Copy the data again and move the app to the copy in one release:

``sh deplane db import --name APP-db-final --mode copy --yes # paste DATABASE_PUBLIC_URL at the prompt deplane db switch APP-db-final --from APP-db ``

  1. Switch DNS to the target deplane domains add showed, and wait for the certificate.
  2. Keep the Railway project until the app has run well on Deplane; then remove the Postgres TCP proxy and delete the project.
  3. Delete the rehearsal's database: deplane db destroy APP-db.
  4. Delete the Railway token (the project's Settings → Tokens).

Limits

The Heroku import's limits apply: Postgres up to 5 GB and versions as for every Postgres import, a new 256 MB Redis without its data, 10 workers and cron jobs per app, sizes up to 2 GB, and copying the database needs a person logged in to the CLI. Railway's API allows 100 calls an hour on its Free plan and 1000 on Hobby; an import makes about 5, plus 5 for each service in the environment.

This page is also available as Markdown. AI agents can start at /llms.txt.