---
title: "Move your PostgreSQL database from Zeabur to Zenavo: restore backups and verify data"
description: "Upload and restore a Zeabur PostgreSQL backup directly in Zenavo, understand how major versions, roles and pg_dumpall cluster dumps are handled, and verify your tables before switching traffic."
date: 2026-11-10
language: en
url: https://zenavo.app/blog/migrate-zeabur-postgresql
---

# Move your PostgreSQL database from Zeabur to Zenavo: restore backups and verify data

When migrating from Zeabur, importing a template recreates your services in one step, while your database rows come across through a backup.

Zenavo natively accepts the PostgreSQL backup archive you download from Zeabur — no local unzipping or SQL editing required. This guide covers restoring a Zeabur PostgreSQL backup into Zenavo, checking your data, and cutting over your app. For the full project migration workflow, read this alongside our [Zeabur migration guide](https://zenavo.app/blog/migrate-from-zeabur).

## 1. Download the backup from Zeabur

Download a backup from your PostgreSQL service in Zeabur and note two things:

- **The PostgreSQL major version** (such as 15, 16 or 17);
- **The database name your app actually uses**.

The file Zeabur downloads is usually a `.zip` archive (even when its filename ends in `.sql.gz`, the outer container is often a ZIP) holding a `pg_dumpall` cluster SQL dump. **Keep the downloaded file as-is** — Zenavo accepts Zeabur's `.zip` backup archives directly, as well as plain `.sql` and `.sql.gz` dumps.

## 2. Create an empty PostgreSQL service on the same major version

In your target Zenavo project, click **Add Service → Database → PostgreSQL**, choose **the same major version as on Zeabur**, and deploy.

Three things to watch:

- **Match the major version first**: Zenavo blocks restoring a cluster dump from a newer major version (such as PG 18) into an older one (such as PG 17). Move across on the same version first, and upgrade later if needed.
- **Keep the target database empty**: don't start an app service that automatically runs migrations before you restore the backup. If the target database already has tables, a cluster restore will refuse to overwrite it.
- **Check extensions**: if your database uses extensions such as PostGIS or `pgvector`, make sure the target image includes them.

## 3. Upload and restore the backup

Open the **Backup & Restore** tab on your new PostgreSQL service, click upload, select the backup file you downloaded from Zeabur in step 1, and run the restore.

Because a Zeabur backup is a `pg_dumpall` cluster export, Zenavo automatically converts it during restore (see [Uploading a backup](https://docs.zenavo.app/operations/backups#uploading-a-backup)):

- Restores your application database into the target service's database;
- Creates any application roles referenced in the dump, preserving their passwords and row-level security (RLS) policies;
- Demotes Zeabur's old `root` superuser role to a **non-superuser, no-login role** for safety while keeping its table and object ownership intact;
- Skips the `template1` and `postgres` system databases.

> If a cluster dump contains more than one non-system application database, Zenavo will ask you to split them first. Nearly all Zeabur projects have a single application database and restore directly.

If a restore fails midway (for example, because of a missing extension), delete the half-restored PostgreSQL service and create a fresh empty one before retrying rather than restoring over partial tables.

## 4. Verify tables and row counts

Once the restore finishes, open the PostgreSQL service's **[Database View](https://docs.zenavo.app/deploy/databases#database-view)** to run read-only SQL checks right in the browser.

First check that all your application tables are present:

```sql
SELECT table_schema, table_name
FROM information_schema.tables
WHERE table_type = 'BASE TABLE'
  AND table_schema NOT IN ('pg_catalog', 'information_schema')
ORDER BY table_schema, table_name;
```

Then pick a few key tables (such as users or orders) and compare exact row counts and the latest timestamp against Zeabur:

```sql
SELECT count(*) AS row_count, max(created_at) AS latest_created_at
FROM public.orders;
```

(Use `count(*)` rather than estimated table statistics so you get the exact count.)

## 5. Connect your app and cut over

In your application service in the same project, point your database connection variable at the new PostgreSQL service (when the database service is named `postgresql`):

```dotenv
DATABASE_URL=${POSTGRESQL_CONNECTION_STRING}
```

Don't hard-code Zeabur's old `root` username — use the connection variable exported by the new Zenavo database service (which also gives you a fresh password, important after Zeabur's 2026 security incidents).

For a **zero-data-loss cutover**, follow this sequence:

1. Do a dry-run restore with a current backup on Zenavo and verify your app can sign in, query and create records;
2. During a quiet window, pause the app on Zeabur (plus any cron jobs or queue workers) so no new writes land in the old database;
3. Take one final backup on Zeabur and restore it into a clean PostgreSQL service on Zenavo;
4. Start the app on Zenavo and switch your DNS records.

## FAQ

**The restore fails saying the target database is not empty?**
Your app service likely connected to the new database and ran auto-migrations (such as Prisma or TypeORM) before you restored the backup. Stop the app service, recreate a clean PostgreSQL service, **restore the backup first, and then start the app**.

**The restore succeeded, but my app gets `permission denied` or can't log in?**
Zeabur's old `root` superuser is restored with login disabled. Update your app's `DATABASE_URL` to use `${POSTGRESQL_CONNECTION_STRING}` from the Zenavo PostgreSQL service (which connects as `postgres` with the new password).

**The file from Zeabur ends in `.sql.gz` and won't gunzip?**
That's a quirk of how Zeabur names its downloads — the file is actually a `.zip` archive. Don't rename or unpack it; upload it directly in Zenavo's **Backup & Restore** tab and Zenavo will detect the format automatically.

Once your database is restored and verified, enable scheduled backups in **Backup & Restore**. For the rest of the migration steps, see the [full Zeabur migration guide](https://zenavo.app/blog/migrate-from-zeabur).
