# Move from Railway to Naijacloud

Source: https://naijacloud.com/guides/migrate-from-railway

Your Railway service running on Naijacloud as a web service, with its variables, its Postgres data and its domain, and the Railway project kept as a rollback.

_60 min · Intermediate · Last verified 2026-10-07 · Stack: postgres, dns_

## What things are called here

| On Railway | On Naijacloud |
| --- | --- |
| Project | Project |
| Service from a repo | Web service from GitHub or a public Git URL |
| Service from a Docker image | Web service from a Docker image |
| Environment | Environment in a project |
| Postgres | Postgres database |
| MySQL, MongoDB | MySQL, MariaDB or MongoDB database |
| Redis | Cache (Redis or Valkey) |
| Cron schedule on a service | Cron job, in UTC, up to 1 hour per run |
| Shared and reference variables | (none) No references. Set the resolved value on each service |
| Volumes | (none) No attached disks. Use object storage |
| railway.json / railway.toml | (none) No config file. Service settings in the dashboard or the CLI |
| Usage-based billing | A fixed hourly rate per size, in naira, from a prepaid balance |

## Before you move: what Railway has that we don't

- Billing by actual CPU and memory use. An idle service costs the same here as a busy one of its size.
- Volumes attached to a service.
- Reference variables that resolve another service’s values.
- The template gallery.
- A SOC 2 report.
- Regions outside Africa and Europe.

If your app depends on one of these, stay on Railway for now.

## The cutover, in order

1. **Lower DNS TTL**: 48 hours before. Set the record to 60 seconds.
2. **Deploy here and add the domain**: Traffic still goes to Railway.
3. **Certificate issued**: Wait for it before you touch DNS, where you can.
4. **Copy the data**: Dump, restore, compare the counts.
5. **Switch DNS**: Point the record at Naijacloud.
6. **Keep the old project 7 days**: Going back is one DNS change.

## Lower the DNS TTL, 48 hours before

At your DNS provider, set the TTL on the record that points your domain at Railway to 60 seconds, then wait at least as long as the old TTL.

## Deploy here and add the domain

In the dashboard, create a **Database** (**Postgres**) and copy its **Internal URL**. Then create a **Web service** from the same repository and branch, or from the same Docker image if Railway deploys one. Copy Railway’s custom build and start commands across if you set any.

Export the service’s variables from Railway and load them here:

```sh
$ railway link
$ railway variables --kv > railway.env
$ npm install -g @naijacloud/cli
$ naijacloud login
$ naijacloud env import railway.env --service my-app
```

Reference variables come out of `railway variables` already resolved, pointing at Railway’s hosts. Delete `DATABASE_URL`, any `REDIS_URL` and every `RAILWAY_` variable from the file before importing, then set `DATABASE_URL` to the new database’s Internal URL under **Variables** and run `naijacloud redeploy my-app`. Test the app on its naijacloud.app address.

Then open **Domains**, enter your domain in **Custom domain** and click **Add domain**. Add the records it lists that prove ownership and issue the certificate. Don’t change the routing record yet.

## Wait for the certificate

Where the **Domains** table lists ownership and HTTPS records, the certificate is issued while traffic is still on Railway. Wait until the domain shows **Verified · HTTPS ready**.

> **Warning: Never move DNS before the certificate is issued here**
>
> If the record points at us while we hold no certificate for the domain, every request fails TLS — a hard browser error, not a slow page — until issuance finishes.

If the table lists only one routing record (an **A** record, as it does for a root domain and in some regions), the certificate is issued in the minutes after the record points here. Plan the switch for a quiet hour.

## Copy the data

Use PostgreSQL 18 client tools. Railway’s Postgres service has a `DATABASE_PUBLIC_URL` variable for connections from outside Railway; use that one. On Naijacloud, add your IP under the database’s **External access** → **Specific IPs**, switch **Connection** to **External · TLS** and copy the **Connection URL**.

```sh
$ pg_dump --format=custom --no-owner --no-acl \
    "$DATABASE_PUBLIC_URL" -f app.dump
$ pg_restore --clean --if-exists --no-owner --no-acl \
    --dbname "$NAIJACLOUD_DATABASE_URL" app.dump
```

**How to know the restore is complete.** Run `analyze;` on both databases first — `n_live_tup` is only an estimate until you do. Then compare the table list, exact counts on your two or three largest tables, the sequence values, and the extension list. Matching row counts with a sequence still sitting at 1 means the next insert will collide.

```sql title="verify.sql · run on both, compare line for line"
analyze;
select relname, n_live_tup from pg_stat_user_tables order by relname;
select count(*) from orders;                    -- your largest table
select last_value from orders_id_seq;           -- sequences advanced
select extname from pg_extension order by 1;    -- extensions present
```

> **Warning: Check the restore before you switch DNS**
>
> Compare the output from both databases. If it differs, or pg_restore printed errors, fix it now. Once DNS moves, new writes go to the new database and the two copies drift apart. If Railway is still taking writes, take a fresh dump just before step 5.

If a Railway service writes files to a volume, move them to a bucket in **Object storage** and change the code to write there; there is no disk to copy them to. [Add file uploads with object storage](https://naijacloud.com/guides/file-uploads-storage.md) shows the client setup.

## Switch DNS

At your DNS provider, replace Railway’s record with the routing record shown in **Domains**. With a 60-second TTL, most visitors follow within minutes. Leave the custom domain on the Railway service.

## Keep the old project for 7 days

Leave the Railway service and its Postgres running. Its `up.railway.app` address keeps working, which makes it easy to check the old version still answers if you need it.

> **Warning: Don’t delete the Railway Postgres yet**
>
> It’s your only copy of the data from before the move. After 7 days, check nothing still calls the old address, then remove the services and raise the TTL again.

## Rollback: keep these for 7 days

- The Railway service, still deployed
- The Railway Postgres service and its volume
- The app.dump file
- The 60-second TTL on your record

To go back: point the record at Railway again. Its up.railway.app address shows the old version is still running.

All guides: https://naijacloud.com/guides · Index for agents: https://naijacloud.com/llms.txt
