# Move from Vercel to Naijacloud

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

Your Next.js app running on Naijacloud as a web service, with its environment variables, its Postgres data and its domain, and the Vercel project kept as a rollback.

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

## What things are called here

| On Vercel | On Naijacloud |
| --- | --- |
| Project | Web service running next start, or a static site for a static export |
| Serverless Functions and Route Handlers | Part of the web service. One long-running process, no per-function timeout |
| Middleware | Runs inside the web service, in its region |
| Edge Functions and the Edge Runtime | (none) No edge locations. Code runs in your service’s region |
| Image Optimization | next/image optimises on the web service itself |
| Cron Jobs | Cron job running a command, in UTC, up to 1 hour per run |
| Vercel Postgres, Neon, Supabase | Postgres database on the private network |
| Vercel Blob | Object storage, S3-compatible |
| Environment Variables (Production, Preview, Development) | Variables, scoped per environment |
| vercel.json | (none) No config file. Service settings in the dashboard or the CLI |
| Edge Config | (none) No equivalent. Use variables, read at start |
| Web Analytics and Speed Insights | (none) No equivalent |

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

- A global edge network. Static files and functions served from many locations; we serve from your service’s region.
- Edge Functions and the Edge Runtime.
- Incremental Static Regeneration served from the edge.
- Web Analytics and Speed Insights.
- Comments on preview deployments.
- Functions that scale to zero between requests. A web service here is always running.
- A SOC 2 report.

If your app depends on one of these, stay on Vercel 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 Vercel.
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 your domain’s record to 60 seconds and wait at least as long as the old TTL. If Vercel runs your DNS (the domain uses Vercel’s nameservers), you’ll make the record changes in Vercel’s dashboard; that’s fine, as long as you leave the nameservers alone until this move is done.

## Deploy here and add the domain

Decide the shape first. If `next.config` sets `output: "export"`, deploy the `out` folder as a static site. Otherwise create a **Web service** from your GitHub repository. Naijacloud detects Next.js and fills in `npm ci && npm run build` and `npm start`, which runs `next start`.

Pull your production variables from Vercel:

```sh
$ npm install -g vercel
$ vercel link
$ vercel env pull .env.production.local --environment=production
```

Open the file and drop every `VERCEL_` and `NEXT_PUBLIC_VERCEL_` variable: Vercel’s runtime sets those, and here they mean nothing. If your code builds absolute links from `VERCEL_URL`, give it your own variable instead. Then load the rest onto the web service, either through **Variables** → **Bulk edit**, or with the CLI:

```sh
$ npm install -g @naijacloud/cli
$ naijacloud login
$ naijacloud env import .env.production.local --service my-app
```

> **Warning: NEXT_PUBLIC_ values are public and fixed at build time**
>
> Next.js writes `NEXT_PUBLIC_` values into the bundle when it builds. Naijacloud passes variables with a public prefix (`NEXT_PUBLIC_`, `VITE_`, `PUBLIC_` and the like) to the build as well as to the running app, so set them in **Variables** with the rest, and redeploy after you change one. Only those prefixes reach the build. Never give a secret one of them: it ends up in the JavaScript every visitor downloads. If your repo has its own Dockerfile, declare each one there as an `ARG`.

Create a **Database** (**Postgres**) and set `DATABASE_URL` on the web service to its **Internal URL**. If your app migrates its schema, run the migration in the start command, for example `npx prisma migrate deploy && npm start`. Redeploy and test the app on its naijacloud.app address against the empty database.

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 record that routes traffic yet.

## Wait for the certificate

Where the **Domains** table lists ownership and HTTPS records, the certificate is issued while traffic is still on Vercel. 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

Skip this step if your data stays where it is: you can keep a Neon or Supabase database and only move the app, by setting `DATABASE_URL` to the provider’s connection string. The database then sits outside our private network.

To move it, use PostgreSQL 18 client tools. Dump with the provider’s **non-pooled** connection string (`POSTGRES_URL_NON_POOLING` on Vercel Postgres): a dump through a transaction-mode pooler can fail partway. 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 \
    "$POSTGRES_URL_NON_POOLING" -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 the old database is still taking writes, take a fresh dump just before step 5.

Vercel Cron Jobs call a path on your app on a schedule. Recreate each one as a **Cron job** whose command calls the same path, for example `curl -fsS https://my-app.naijacloud.app/api/digest`, with the same schedule in UTC.

## Switch DNS

At your DNS provider, replace Vercel’s record with the routing record shown in **Domains**. Don’t keep both: two A records for one name send half your visitors to each platform. With a 60-second TTL most visitors follow within minutes. Leave the domain attached to the Vercel project.

## Keep the old project for 7 days

Leave the Vercel project, its last production deployment and the domain on it. If something goes wrong, point the record back at Vercel.

> **Warning: Don’t delete the old project yet**
>
> Deleting the Vercel project or the old database removes your way back. After 7 days, check nothing still calls the old address, then remove them and raise the TTL again.

## Rollback: keep these for 7 days

- The Vercel project and its last production deployment
- The domain attached to the Vercel project
- Your old database, untouched
- The app.dump file
- The 60-second TTL on your record

To go back: point the record at Vercel again. The last production deployment is still there.

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