Migrate to Zenifra
This plan helps you move a production app from another platform to Zenifra with minimal downtime. The idea is simple: run everything in parallel, validate on the Zenifra URL, and only then switch DNS.
Seven-step plan
Take inventory
List every service in the current app: web processes, workers, scheduled tasks, databases, cache, environment variables, domains, and external integrations. Each process becomes a project on Zenifra.
Create the organization and invite the team
Create or pick an organization and invite the people involved with the permissions they need.
Create databases and managed services
Create the databases, cache, and queues before the app. That way the connection URLs already exist when you add the variables.
Deploy the app
Use your framework guide and the equivalents table below. Copy the environment variables from the current platform, replacing database and cache URLs with the new ones.
Copy the data
Follow Migrate the database. Do a full rehearsal before switch day to measure how long it takes.
Validate on the Zenifra URL
Test the app on *.clients.zenifra.com: sign-in, main flows, email sending, webhooks, and integrations.
Switch DNS
Lower the DNS record TTL to 300 seconds a day ahead. At the agreed time, freeze writes on the old platform, run the final data copy, configure the domain on Zenifra, and update DNS. Keep the old platform running for a few days for rollback.
Platform equivalents
| Heroku | Zenifra |
|---|---|
| App | Project |
web dyno in Procfile | Project start command |
worker dyno | Another project from the same repository with a different start |
release: in Procfile | Prefix in start, such as npm run migrate && npm start |
| Config Vars | Environment variables |
| Heroku Postgres | Managed PostgreSQL |
| Heroku Redis | Managed cache or Key-Value |
| Buildpacks | Node.js or Python runtime, or OCI Image for other languages |
| Review Apps | Preview Environments |
$PORT | Project Port field. Set PORT as a variable if your code depends on it |
Migrate the database
PostgreSQL
Export the current database in custom format and restore it on Zenifra with the console URI, which already enforces TLS:
pg_dump --format=custom --no-owner --no-acl "$OLD_URL" > dump.pgdump
pg_restore --no-owner --no-acl --jobs=4 \
--dbname="postgresql://user:password@host:port/db?sslmode=verify-full&sslrootcert=system" \
dump.pgdumpUse a pg_dump version equal to or newer than the source database. --no-owner avoids permission errors with users that do not exist on Zenifra.
MariaDB and MySQL
mysqldump --single-transaction --routines --triggers -h OLD_HOST -u USER -p DATABASE > dump.sql
mariadb --ssl -h ZENIFRA_HOST -P PORT -u USER -p DATABASE < dump.sqlValidation
Compare row counts of the main tables in both databases and run the app's smoke tests against the new database.
Files and uploads
Copy files from the current disk or bucket to the new destination before the switch. If you use persistent storage, a practical approach is to expose a temporary password-protected import endpoint and remove it afterwards.
Switch-day checklist
- DNS TTL lowered in advance
- App validated on the
*.clients.zenifra.comURL - Variables reviewed, with no URLs from the old platform
- External webhooks (payments, GitHub, email) updated to the new domain
- Final data copy done and validated
- Domain configured and HTTPS active
- Old platform kept running for rollback
Need help migrating?
For larger migrations, email [email protected] with the inventory from step 1. See also the help center.
Next steps
Last updated on