Migrate from Railway
Move Railway services, their database and variables.
A Railway project is a set of services connected through variable references. On Nodion, a service with its own code becomes an
application, workers from the same code become extra processes of that app, and databases become managed databases you attach to
the app. Nodion does not read railway.json or railway.toml; Railway itself is retiring
Config as Code (hard cutoff 2026-12-01), so you move the
settings by hand.
What maps to what
| Railway | Nodion |
|---|---|
| Project | Project |
| Service with its own code | Application |
| Worker service from the same repo | Extra process of the app |
| Railpack or Nixpacks | Nodion buildpacks |
| Dockerfile | Dockerfile strategy |
| Start command | Process command (Processes tab) |
| Pre-deploy command | Release command or Procfile release: entry |
| Cron schedule on a service | Cron job on the app |
| Variables | Environment variables (Environment tab) |
References like ${{Postgres.DATABASE_URL}} | Attached database that sets DATABASE_URL |
Private networking (*.railway.internal) | <slug>.internal for databases, <app>.app.internal for apps |
| PR environments | Preview environments |
| Volumes | Volumes |
1. Create the project and the databases
Create a project and, in it, the databases your Railway project uses, in the region the apps should run in. For Postgres, pick a
version at least as new as on Railway. Instead of Redis, Nodion offers Valkey, also attached as REDIS_URL. An empty
Valkey is only enough for caches or queues you let drain first; if you need the keys from Redis, move them before you delete the
Railway project. More on Databases.
2. Copy the database
Railway databases are private by default. For the dump you reach one in one of two ways: either turn on public access under
Settings, Networking; Railway then creates a TCP proxy and sets DATABASE_PUBLIC_URL
(Railway docs), and bills traffic over the proxy as egress. Or keep the
database private and open a tunnel with the Railway CLI, after linking the project with railway link. Railway's built-in volume
backups only restore into the same project, so a move needs pg_dump.
Stop writes from your services, then create the dump as Railway's
backup guide shows. Over public access,
use the value of DATABASE_PUBLIC_URL from the database service's variables:
bashpg_dump "postgresql://postgres:PASSWORD@PROXY_HOST:PROXY_PORT/railway" \
--format=custom --no-owner --file=railway.dump
Through the tunnel, first link the project with railway link, then open the tunnel and, in a second terminal, dump against localhost with the port the CLI prints:
bashrailway link
railway connect postgres --tunnel-only
# second terminal
pg_dump "postgresql://postgres:PASSWORD@localhost:TUNNEL_PORT/railway" \
--format=custom --no-owner --file=railway.dump In Nodion, open the database's Overview tab and click Enable public access. Once the endpoint no longer shows Provisioning, copy the connection URL (always TLS) and add your own IP under Allowed sources. Then restore:
bashpg_restore --verbose --no-owner --no-acl \
--dbname "postgresql://nodion:PASSWORD@HOST:PORT/DATABASE?sslmode=require" \
railway.dump
Use a pg_restore at least as new as the newer of the two servers. Check row counts on the Browse tab, then turn public
access off again, and on Railway as well.
3. Create the application and its processes
Create one application per code service from its Git repository. If Railway built with Railpack or Nixpacks, use the Buildpacks
strategy (Buildpacks); if it found a Dockerfile, use the Dockerfile strategy. Unlike
Railway, Nodion does not pick the strategy for you; you set it.
Railway injects PORT for your services. Nodion sets PORT only for the web process of buildpack
apps; on Dockerfile apps the app listens on the web process port (else the image's EXPOSE, else 8080).
If a second service ran from the same repo with only another start command, a worker for example, add it under Processes, New process
as another process of the same app and enter the start command there. Move a pre-deploy command to a release: line in the
Procfile (buildpacks) or to the app's release command (Settings, in the Preview environments card, where the field shows once previews are enabled, or
release_command over the API). It runs once per deploy before web; if it fails, the previous release stays live.
4. Move the variables
Print a service's variables as KEY=value lines (Railway CLI):
bashrailway variable list --kv > railway.env
Paste the lines into Environment, Add many. The Railway CLI does not print sealed variables
(Railway docs); set those by hand, as secrets with
nodion env set KEY=value --secret. Check values with quotes, and set values that span several lines through the CLI or API.
Nodion has no references like ${{shared.KEY}} or ${{otherService.KEY}}. Check every imported variable: it
must hold the actual value, not the reference text. Where a reference pointed at another service, set that service's internal hostname
on Nodion instead (<app>.app.internal), or attach the database.
Delete the variables that point at a Railway database (DATABASE_URL, REDIS_URL) again: a variable you set
yourself overrides the value of an attached database. Attach the databases with Attach database. Inside Nodion the
connection runs without TLS (sslmode=disable); if your code forces SSL, turn that off for this URL.
5. Move cron
On Railway a cron job is its own service that runs and exits (Railway docs). On Nodion you add it on the Cron tab of the app whose code it needs: a five-field schedule in UTC, the command, a timeout of up to 30 minutes, up to 8 jobs per app. It runs with the app's active release and environment variables.
6. Deploy, move the domain, shut down Railway
Deploy and check the Logs tab. Then add the domain on the Domains tab and set the two records Nodion shows: TXT
_nodion-challenge.your-domain and a CNAME (an ALIAS at the apex) to the app's default hostname. The certificate follows once
the CNAME points at Nodion; expect a few minutes without a valid certificate and lower the TTL beforehand. When everything runs, delete the Railway project; Railway calls this permanent.
bashrailway delete --project my-project --yes What works differently
- There are no environments such as production and staging inside one project; use separate apps or projects.
- There are no shared variables or references; database values come from attaching the database.
- Cron jobs run on an existing app, not as a service of their own.
- The CLI fetches logs but cannot follow them; watch them live on the Logs tab.
Next
Nodion compared with Railway, Pricing, Applications and Databases.