Migrate from Railway to Bahriya
Railway runs each part of your app as a service, builds from your repository, and stores configuration as variables shared across services. Bahriya uses the same service model but deploys a container image you build, across the regions you choose, with configuration supplied as environment variables and secrets. This guide maps each Railway concept to Bahriya and walks the move.
Railway runs each part of your app as a service, builds from your repository, and stores configuration as variables shared across services. Bahriya uses the same service model but deploys a container image you build, across the regions you choose, with configuration supplied as environment variables and secrets. This guide maps each Railway concept to Bahriya and walks the move.
What maps to what
| Railway | Bahriya |
|---|---|
| Project | A project |
| Service | A container — HTTP, worker, or cron job |
| Build from repo (Nixpacks) / Dockerfile | A Dockerfile producing an image |
| Variables | Environment variables and secrets |
| Shared variables | Secrets attached to the project |
| Database / Redis plugin | An external database or Bahriya Memcached via a connection secret |
PORT variable | The port you declare with --port |
| Replicas | Replicas and autoscaling |
| Generated domain + custom domains | Default hostname with automatic TLS + custom domains |
1. Containerise
If your Railway service already uses a Dockerfile, carry it over. If it builds from source, write a Dockerfile that installs dependencies and starts your app on a single port:
FROM node:22-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE 8080
CMD ["node", "server.js"]Railway injects a PORT variable and expects your app to bind to it. Keep reading the port from the environment and bind to 0.0.0.0, then declare it with --port on Bahriya (default 8080). Build and push the image:
docker build -t ghcr.io/myorg/api:v1.0.0 .
docker push ghcr.io/myorg/api:v1.0.02. Variables to env and secrets
Railway keeps configuration in service and shared variables. On Bahriya, split them:
- Non-sensitive values become plain environment variables, visible in the Console.
- Sensitive values (database URLs, API keys, tokens) become secrets — encrypted at rest, injected as env vars, and wired to the variable name your app already reads.
Railway lets services reference each other's variables (for example a database URL exposed to the app automatically). On Bahriya those links are explicit: take the connection string from your database and store it as a secret, then wire it into the app container yourself.
3. Plugins and databases
Railway plugins provision a managed database or cache and expose a connection URL as a variable. On Bahriya:
- Database. Run your database with a managed provider or your own instance, reachable over the network. Store the connection string as a secret wired to
DATABASE_URL. Provision, migrate your data, and verify connectivity from a Bahriya container before cutting over. - Cache. For a Memcached-compatible cache, create a Bahriya Memcached instance. For Redis or another engine, connect to an external instance via a secret.
4. Scaling
Railway scales services by replica count and resource limits. On Bahriya, set minimum CPU (millicores) and memory (MB), a replica count, and — for automatic scaling — a maximum replica count. Setting --max_replicas above --replicas enables autoscaling. See Resources and Scaling.
5. Deploy
From the Console follow Deploy Your First Container, or with Reis:
reis container:create \
--type http \
--name "Web API" \
--handle web-api \
--image ghcr.io/myorg/api:v1.0.0 \
--registry ghcr \
--port 8080 \
--healthcheck /healthz \
--replicas 2 \
--max_replicas 8 \
--regions falkenstein-1 \
--regions virginia-1 \
--env NODE_ENV=production \
--secrets DATABASE_URL=database-urlDeploy a background service the same way with --type worker, and a scheduled task with --type cronjob. Choose regions close to your users — see Regions.
6. Point your domain and cut over
Your container is reachable at https://web-api.<region>.x.on.bahriya.app with automatic TLS. Test there, then add your production domain, verify it, and move DNS across — see Custom Domain Setup. Keep the Railway service running until traffic has drained, then remove it.