Migration
PORTABLE ZERO LOCK-IN

Migrate to Lampion

Lampion runs standard PostgreSQL. No proprietary layer, no fork. Migrate from any provider in a few minutes with pg_dump and pg_restore.

01

Overview

A migration to Lampion always follows the same pattern: export, create, restore, verify, switch. Most migrations take less than 10 minutes for a database < 5 GB.

EXPORT
pg_dump from the source provider
CREATE
Create a Lampion project
RESTORE
pg_restore into Lampion
SWITCH
Switch the connection string

Prerequisites — PostgreSQL client tools (pg_dump, pg_restore, psql) version ≥ 17. On Debian/Ubuntu: apt install postgresql-client-17. On macOS: brew install postgresql@17.

02

Export the source database

Grab a full dump from your current provider. The custom format (-Fc) is recommended: it is compressed, supports parallel restore, and allows filtering at restore time.

pg_dump — Custom format (recommended)
$ pg_dump "postgresql://user:[email protected]:5432/mydb" \
  --format=custom \
  --no-owner \
  --no-privileges \
  --file=mydb.dump

-- Dump complete: mydb.dump (124 MB)

Why --no-owner and --no-privileges ? Lampion uses its own cloud_adminrole. These flags avoid role "xxx" does not exist errors at restore time.

03

Create the Lampion project

Create a project via the console or the API. You get a ready-to-use connection string immediately.

Web console
2. Click New Project
3. Choose a name and a region
4. Copy the connection string
REST API
$ curl -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"name":"my-app"}' \
  api.lampion.cloud/v1/projects

{"connection_string":"...",
 "pg_password":"..."}
04

Restore the dump

Use the Lampion connection string as the target. The --jobs=4 flag parallelizes the restore and speeds up the process for large databases.

pg_restore — Into Lampion
$ pg_restore \
  --dbname="postgresql://cloud_admin:[email protected]:5432/ep-abc.postgres?sslmode=require" \
  --no-owner \
  --no-privileges \
  --jobs=4 \
  --verbose \
  mydb.dump

pg_restore: connecting to database for restore
pg_restore: creating SCHEMA "public"
pg_restore: creating TABLE "public.users"
pg_restore: processing data for table "public.users"
pg_restore: creating INDEX "users_email_key"
-- Restore completed in 47 seconds

Databases > 10 GB — Temporarily resize the compute via the console (4-8 CU) before the restore, then scale back down to 0.25 CU. You save on restore time and cost.

05

Verify the migration

Compare the number of tables, indexes, and row counts for each critical table.

psql — Consistency checks
# Number of tables
$ psql "$LAMPION_URL" -c "\dt"

# Row count per table
$ psql "$LAMPION_URL" -c "
  SELECT schemaname, relname, n_live_tup
  FROM pg_stat_user_tables
  ORDER BY n_live_tup DESC;"

# Existing indexes
$ psql "$LAMPION_URL" -c "\di"

# Compare against the source
$ psql "$SOURCE_URL" -c "
  SELECT schemaname, relname, n_live_tup
  FROM pg_stat_user_tables
  ORDER BY n_live_tup DESC;"

ANALYZE post-restore — pg_restore does not run ANALYZE automatically. Run VACUUM ANALYZE so the planner has fresh statistics on your migrated tables.

06

Switch traffic

Update the DATABASE_URL of your applications. To minimize downtime, set the source to read-only during the switch.

Recommended procedure (minimal downtime)
1. Full migration a first time (no cutover)
2. Application tests against Lampion in parallel
3. Maintenance window: set the source to read-only
4. Incremental dump of the latest writes
5. Restore into Lampion
6. Update DATABASE_URL and redeploy
7. Keep the source on standby for 24-48h
07

Provider guides

Specifics per source provider. The logic stays the same everywhere: export, restore, switch.

Neon — Direct migration, similar architecture

Neon uses the same architecture (pageserver/safekeeper). The migration is trivial.

# 1. Grab the Neon connection string (Dashboard → Connection Details)
$ pg_dump "postgresql://user:[email protected]/neondb?sslmode=require" \
    -Fc --no-owner --no-privileges -f neon.dump

# 2. Restore into Lampion
$ pg_restore -d "$LAMPION_URL" --no-owner --no-privileges -j 4 neon.dump
Supabase — Watch out for the auth

Supabase adds system schemas (auth, storage, realtime). Filter on public only, unless you want to migrate everything.

# Grab the DB password (Settings → Database)
$ pg_dump "postgresql://postgres:[PASSWORD]@db.[REF].supabase.co:5432/postgres" \
    --schema=public \
    -Fc --no-owner --no-privileges -f supabase.dump

$ pg_restore -d "$LAMPION_URL" --no-owner --no-privileges -j 4 supabase.dump
AWS RDS / Aurora PostgreSQL

Make sure your IP is in the RDS security group. For large instances, run the dump from an EC2 instance in the same VPC to avoid outbound transfer costs.

# From your machine (or an EC2 instance in the same VPC)
$ pg_dump "postgresql://admin:[email protected]:5432/myapp?sslmode=require" \
    -Fc --no-owner --no-privileges -f rds.dump

$ pg_restore -d "$LAMPION_URL" --no-owner --no-privileges -j 4 rds.dump
Heroku Postgres — Via the Heroku CLI

The Heroku CLI provides pg:backups to generate a downloadable compressed dump.

# 1. Capture a backup
$ heroku pg:backups:capture -a my-app

# 2. Download the dump
$ heroku pg:backups:download -a my-app
-- latest.dump (89 MB)

# 3. Restore into Lampion
$ pg_restore -d "$LAMPION_URL" --no-owner --no-privileges -j 4 latest.dump
GCP Cloud SQL

Temporarily enable the public IP, or use the Cloud SQL Auth Proxy to connect locally.

# With Cloud SQL Auth Proxy
$ cloud-sql-proxy --port 5433 my-project:europe-west1:my-instance &

$ pg_dump "postgresql://postgres:[email protected]:5433/myapp" \
    -Fc --no-owner --no-privileges -f cloudsql.dump

$ pg_restore -d "$LAMPION_URL" --no-owner --no-privileges -j 4 cloudsql.dump
Self-hosted PostgreSQL — Bare metal, VM, Docker, Kubernetes

If you host your own PostgreSQL, you can run pg_dump directly on the host or over SSH. Advantage: no bandwidth limit imposed by a provider.

# On the source server
$ sudo -u postgres pg_dump myapp -Fc --no-owner --no-privileges -f /tmp/myapp.dump

# Transfer locally
$ scp [email protected]:/tmp/myapp.dump .

# Restore into Lampion
$ pg_restore -d "$LAMPION_URL" --no-owner --no-privileges -j 4 myapp.dump
08

Common gotchas

The most frequent issues and how to fix them.

EXTENSIONS Missing extension at restore time

If your source uses pgvector, postgis or others, install them on Lampion before the restore via the console (Settings → Extensions) or the API.

$ curl -X POST -H "Authorization: Bearer $TOKEN" \
  -d '{"name":"pgvector"}' \
  api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/extensions
ROLES Role "xxx" does not exist

Always use --no-owner --no-privileges on both dump AND restore. If you need specific application roles, create them after the restore via the Roles section of the console or the API.

SEQUENCES Out-of-sync sequences

If you dumped and then wrote to the source before the cutover, sequences may be behind. Resync them after the switch:

SELECT setval(pg_get_serial_sequence('users', 'id'),
              (SELECT MAX(id) FROM users));
PERFORMANCE Databases > 50 GB

For very large databases: (1) resize the Lampion compute to 8 CU before the restore, (2) use --jobs=8, (3) dump by schema or by table if possible so you can resume after a failure, (4) open a support ticket before the migration to get hands-on help.

TLS SSL connection required

Lampion requires TLS 1.3 on all connections. Always append ?sslmode=require to the connection string if your client does not do it automatically.

ENCODING Encoding and collation

Lampion uses UTF8 and the en_US.utf8 collation by default. If your source uses a different collation, create the database manually with the right collation before the restore.

Ready to migrate?

Create your account, create a project, and run your first pg_restore.